Skip to content

Method: generateIdentifier(URI)

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