Skip to content

Method: update(AxiomValueDescriptor)

1: /*
2: * JOPA
3: * Copyright (C) 2024 Czech Technical University in Prague
4: *
5: * This library is free software; you can redistribute it and/or
6: * modify it under the terms of the GNU Lesser General Public
7: * License as published by the Free Software Foundation; either
8: * version 3.0 of the License, or (at your option) any later version.
9: *
10: * This library is distributed in the hope that it will be useful,
11: * but WITHOUT ANY WARRANTY; without even the implied warranty of
12: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13: * Lesser General Public License for more details.
14: *
15: * You should have received a copy of the GNU Lesser General Public
16: * License along with this library.
17: */
18: package cz.cvut.kbss.ontodriver.rdf4j;
19:
20: import cz.cvut.kbss.ontodriver.Closeable;
21: import cz.cvut.kbss.ontodriver.Wrapper;
22: import cz.cvut.kbss.ontodriver.descriptor.AxiomDescriptor;
23: import cz.cvut.kbss.ontodriver.descriptor.AxiomValueDescriptor;
24: import cz.cvut.kbss.ontodriver.exception.IdentifierGenerationException;
25: import cz.cvut.kbss.ontodriver.exception.OntoDriverException;
26: import cz.cvut.kbss.ontodriver.model.Axiom;
27: import cz.cvut.kbss.ontodriver.rdf4j.config.Constants;
28: import cz.cvut.kbss.ontodriver.rdf4j.config.RuntimeConfiguration;
29: import cz.cvut.kbss.ontodriver.rdf4j.connector.RepoConnection;
30: import cz.cvut.kbss.ontodriver.rdf4j.connector.StatementExecutor;
31: import cz.cvut.kbss.ontodriver.rdf4j.exception.Rdf4jDriverException;
32: import cz.cvut.kbss.ontodriver.rdf4j.list.ReferencedListHandler;
33: import cz.cvut.kbss.ontodriver.rdf4j.list.SimpleListHandler;
34: import cz.cvut.kbss.ontodriver.rdf4j.util.Rdf4jUtils;
35: import cz.cvut.kbss.ontodriver.util.IdentifierUtils;
36: import cz.cvut.kbss.ontodriver.util.Transaction;
37: import org.eclipse.rdf4j.model.Resource;
38: import org.eclipse.rdf4j.model.Statement;
39: import org.eclipse.rdf4j.model.Value;
40: import org.eclipse.rdf4j.model.ValueFactory;
41: import org.eclipse.rdf4j.model.vocabulary.RDF;
42:
43: import java.net.URI;
44: import java.util.ArrayList;
45: import java.util.Collection;
46: import java.util.Collections;
47: import java.util.List;
48: import java.util.Set;
49: import java.util.stream.Collectors;
50:
51: class Rdf4jAdapter implements Closeable, Wrapper {
52:
53: /**
54: * Maximum number of attempts to generate a unique identifier
55: */
56: private static final int ID_GENERATION_THRESHOLD = 64;
57:
58: private final RepoConnection connector;
59: private final ValueFactory valueFactory;
60: private final RuntimeConfiguration config;
61: private final Transaction transaction;
62:
63: private boolean open = true;
64:
65: public Rdf4jAdapter(RepoConnection connector, RuntimeConfiguration config) {
66: assert connector != null;
67:
68: this.connector = connector;
69: this.valueFactory = connector.getValueFactory();
70: this.config = config;
71: this.transaction = new Transaction();
72: }
73:
74: RepoConnection getConnector() {
75: return connector;
76: }
77:
78: RuntimeConfiguration getConfig() {
79: return config;
80: }
81:
82: @Override
83: public void close() throws OntoDriverException {
84: if (!open) {
85: return;
86: }
87: try {
88: connector.close();
89: } finally {
90: this.open = false;
91: }
92: }
93:
94: @Override
95: public boolean isOpen() {
96: return open;
97: }
98:
99: void commit() throws Rdf4jDriverException {
100: if (transaction.isActive()) {
101: transaction.commit();
102: connector.commit();
103: transaction.afterCommit();
104: }
105: }
106:
107: void rollback() throws Rdf4jDriverException {
108: if (transaction.isActive()) {
109: transaction.rollback();
110: connector.rollback();
111: transaction.afterRollback();
112: }
113: }
114:
115: boolean isConsistent(URI context) {
116: // RDF4J currently doesn't support any consistency checking functionality
117: return true;
118: }
119:
120: List<URI> getContexts() throws Rdf4jDriverException {
121: final List<Resource> contextIds = connector.getContexts();
122: final List<URI> contexts = new ArrayList<>(contextIds.size());
123: for (Resource res : contextIds) {
124: final URI context = Rdf4jUtils.toJavaUri(res);
125: // We support only named contexts (no blank nodes)
126: if (context != null) {
127: contexts.add(context);
128: }
129: }
130: return contexts;
131: }
132:
133: URI generateIdentifier(URI classUri) throws Rdf4jDriverException {
134: startTransactionIfNotActive();
135: boolean unique = false;
136: URI id = null;
137: int counter = 0;
138: while (!unique && counter++ < ID_GENERATION_THRESHOLD) {
139: id = IdentifierUtils.generateIdentifier(classUri);
140: unique = isIdentifierUnique(id, classUri);
141: }
142: if (!unique) {
143: throw new IdentifierGenerationException("Unable to generate a unique identifier.");
144: }
145: return id;
146:
147: }
148:
149: private void startTransactionIfNotActive() throws Rdf4jDriverException {
150: // TODO Consider whether a transaction should be started for read operations
151: if (!transaction.isActive()) {
152: connector.begin();
153: transaction.begin();
154: }
155: }
156:
157: private boolean isIdentifierUnique(URI identifier, URI classUri) throws Rdf4jDriverException {
158: return !connector.containsStatement(
159: Rdf4jUtils.toRdf4jIri(identifier, valueFactory), RDF.TYPE,
160: Rdf4jUtils.toRdf4jIri(classUri, valueFactory), true, Collections.emptySet());
161: }
162:
163: boolean contains(Axiom<?> axiom, Set<URI> contexts) throws Rdf4jDriverException {
164: startTransactionIfNotActive();
165: final Value value = axiomObjectToRdf4jValue(axiom);
166: return connector.containsStatement(
167: Rdf4jUtils.toRdf4jIri(axiom.getSubject(), valueFactory),
168: Rdf4jUtils.toRdf4jIri(axiom.getAssertion(), valueFactory), value,
169: axiom.getAssertion().isInferred(),
170: contexts.stream().map(c -> Rdf4jUtils.toRdf4jIri(c, valueFactory)).collect(Collectors.toSet()));
171:
172: }
173:
174: private Value axiomObjectToRdf4jValue(Axiom<?> axiom) {
175: final Value value;
176: if (Rdf4jUtils.isResourceIdentifier(axiom.getValue().getValue())) {
177: value = valueFactory.createIRI(axiom.getValue().stringValue());
178: } else {
179: final String lang =
180: axiom.getAssertion().hasLanguage() ? axiom.getAssertion().getLanguage() : Constants.DEFAULT_LANG;
181: value = Rdf4jUtils.createLiteral(axiom.getValue().getValue(), lang, valueFactory);
182: }
183: return value;
184: }
185:
186: boolean isInferred(Axiom<?> axiom, Set<URI> contexts) throws Rdf4jDriverException {
187: startTransactionIfNotActive();
188: final Value value = axiomObjectToRdf4jValue(axiom);
189: final Statement s = valueFactory.createStatement(Rdf4jUtils.toRdf4jIri(axiom.getSubject(), valueFactory),
190: Rdf4jUtils.toRdf4jIri(axiom.getAssertion(), valueFactory), value);
191: return connector.isInferred(s, contexts.stream().map(c -> Rdf4jUtils.toRdf4jIri(c, valueFactory))
192: .collect(Collectors.toSet()));
193: }
194:
195: Collection<Axiom<?>> find(AxiomDescriptor axiomDescriptor) throws Rdf4jDriverException {
196: startTransactionIfNotActive();
197: return new AxiomLoader(connector, config).loadAxioms(axiomDescriptor);
198: }
199:
200: void persist(AxiomValueDescriptor axiomDescriptor) throws Rdf4jDriverException {
201: startTransactionIfNotActive();
202: new AxiomSaver(connector).persistAxioms(axiomDescriptor);
203: }
204:
205: void update(AxiomValueDescriptor axiomDescriptor) throws Rdf4jDriverException {
206: startTransactionIfNotActive();
207: new EpistemicAxiomRemover(connector, valueFactory).remove(axiomDescriptor);
208: new AxiomSaver(connector).persistAxioms(axiomDescriptor);
209: }
210:
211: void remove(AxiomDescriptor axiomDescriptor) throws Rdf4jDriverException {
212: startTransactionIfNotActive();
213: new EpistemicAxiomRemover(connector, valueFactory).remove(axiomDescriptor);
214: }
215:
216: StatementExecutor getQueryExecutor() {
217: return connector;
218: }
219:
220: SimpleListHandler getSimpleListHandler() throws Rdf4jDriverException {
221: startTransactionIfNotActive();
222: return new SimpleListHandler(connector, valueFactory);
223: }
224:
225: ReferencedListHandler getReferencedListHandler() throws
226: Rdf4jDriverException {
227: startTransactionIfNotActive();
228: return new ReferencedListHandler(connector, valueFactory);
229: }
230:
231: TypesHandler getTypesHandler() throws Rdf4jDriverException {
232: startTransactionIfNotActive();
233: return new TypesHandler(connector, valueFactory);
234: }
235:
236: @Override
237: public <T> T unwrap(Class<T> cls) throws OntoDriverException {
238: if (cls.isAssignableFrom(this.getClass())) {
239: return cls.cast(this);
240: } else if (cls.isAssignableFrom(valueFactory.getClass())) {
241: return cls.cast(valueFactory);
242: }
243: return connector.unwrap(cls);
244: }
245: }