1 /**
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 package org.apache.commons.rdf.api;
19
20 import java.util.ConcurrentModificationException;
21 import java.util.Iterator;
22 import java.util.Optional;
23 import java.util.stream.Stream;
24
25 /**
26 * An <a href="http://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset">RDF
27 * 1.1 Dataset</a>, a set of RDF quads, as defined by
28 * <a href="http://www.w3.org/TR/rdf11-concepts/#section-rdf-dataset">RDF-1.1 Concepts and Abstract
29 * Syntax</a>, a W3C Recommendation published on 25 February 2014.
30 *
31 * @since 0.3.0-incubating
32 * @see RDF#createDataset()
33 */
34 public interface Dataset extends AutoCloseable, GraphLike<Quad> {
35
36 /**
37 * Add a quad to the dataset, possibly mapping any of the components of the
38 * Quad to those supported by this dataset.
39 *
40 * @param quad
41 * The quad to add
42 */
43 @Override
44 void add(Quad quad);
45
46 /**
47 * Add a quad to the dataset, possibly mapping any of the components to
48 * those supported by this dataset.
49 *
50 * @param graphName
51 * The graph the quad belongs to, or <code>null</code> for the
52 * default graph
53 * @param subject
54 * The quad subject
55 * @param predicate
56 * The quad predicate
57 * @param object
58 * The quad object
59 */
60 void add(BlankNodeOrIRI graphName, BlankNodeOrIRI subject, IRI predicate, RDFTerm object);
61
62 /**
63 * Check if dataset contains quad.
64 *
65 * @param quad
66 * The quad to check.
67 * @return True if the dataset contains the given Quad.
68 */
69 @Override
70 boolean contains(Quad quad);
71
72 /**
73 * Check if dataset contains a pattern of quads.
74 *
75 * @param graphName
76 * The graph the quad belongs to, wrapped as an {@link Optional}
77 * (<code>null</code> is a wildcard, {@link Optional#empty()} is
78 * the default graph)
79 * @param subject
80 * The quad subject (<code>null</code> is a wildcard)
81 * @param predicate
82 * The quad predicate (<code>null</code> is a wildcard)
83 * @param object
84 * The quad object (<code>null</code> is a wildcard)
85 * @return True if the dataset contains any quads that match the given
86 * pattern.
87 */
88 boolean contains(Optional<BlankNodeOrIRI> graphName, BlankNodeOrIRI subject, IRI predicate, RDFTerm object);
89
90 /**
91 * Close the dataset, relinquishing any underlying resources.
92 * <p>
93 * For example, this would close any open file and network streams and free
94 * database locks held by the dataset implementation.
95 * <p>
96 * The behaviour of the other dataset methods are undefined after closing
97 * the dataset.
98 * <p>
99 * Implementations might not need {@link #close()}, hence the default
100 * implementation does nothing.
101 */
102 @Override
103 default void close() throws Exception {
104 }
105
106 /**
107 * Get the default graph of this dataset.
108 * <p>
109 * The {@link Triple}s of the default graph are equivalent to the
110 * {@link Quad}s in this Dataset which has the {@link Quad#getGraphName()}
111 * set to {@link Optional#empty()}.
112 * <p>
113 * It is unspecified if modifications to the returned Graph are reflected in
114 * this Dataset.
115 * <p>
116 * The returned graph MAY be empty.
117 *
118 * @see #getGraph(BlankNodeOrIRI)
119 * @return The default graph of this Dataset
120 */
121 Graph getGraph();
122
123 /**
124 * Get a named graph in this dataset.
125 * <p>
126 * The {@link Triple}s of the named graph are equivalent to the the Quads of
127 * this Dataset which has the {@link Quad#getGraphName()} equal to the
128 * provided <code>graphName</code>, or equal to {@link Optional#empty()} if
129 * the provided <code>graphName</code> is <code>null</code>.
130 * <p>
131 * It is unspecified if modifications to the returned Graph are reflected in
132 * this Dataset.
133 * <p>
134 * It is unspecified if requesting an unknown or empty graph will return
135 * {@link Optional#empty()} or create a new empty {@link Graph}.
136 *
137 * @see #getGraph()
138 * @see #getGraphNames()
139 * @param graphName
140 * The name of the graph, or <code>null</code> for the default
141 * graph.
142 * @return The named Graph, or {@link Optional#empty()} if the dataset do
143 * not contain the named graph.
144 */
145 Optional<Graph> getGraph(BlankNodeOrIRI graphName);
146
147 /**
148 * Get the graph names in this Dataset.
149 * <p>
150 * The set of returned graph names is equivalent to the set of unique
151 * {@link Quad#getGraphName()} of all the {@link #stream()} of this dataset
152 * (excluding the default graph).
153 * <p>
154 * The returned {@link Stream} SHOULD NOT contain duplicate graph names.
155 * <p>
156 * The graph names can be used with {@link #getGraph(BlankNodeOrIRI)} to
157 * retrieve the corresponding {@link Graph}, however callers should be aware
158 * of any concurrent modifications to the Dataset may cause such calls to
159 * return {@link Optional#empty()}.
160 * <p>
161 * Note that a Dataset always contains a <strong>default graph</strong>
162 * which is not named, and thus is not represented in the returned Stream.
163 * The default graph is accessible via {@link #getGraph()} or by using
164 * {@link Optional#empty()} in the Quad access methods).
165 *
166 * @return A {@link Stream} of the graph names of this Dataset.
167 */
168 Stream<BlankNodeOrIRI> getGraphNames();
169
170 /**
171 * Remove a concrete quad from the dataset.
172 *
173 * @param quad
174 * quad to remove
175 */
176 @Override
177 void remove(Quad quad);
178
179 /**
180 * Remove a concrete pattern of quads from the default graph of the dataset.
181 *
182 * @param graphName
183 * The graph the quad belongs to, wrapped as an {@link Optional}
184 * (<code>null</code> is a wildcard, {@link Optional#empty()} is
185 * the default graph)
186 * @param subject
187 * The quad subject (<code>null</code> is a wildcard)
188 * @param predicate
189 * The quad predicate (<code>null</code> is a wildcard)
190 * @param object
191 * The quad object (<code>null</code> is a wildcard)
192 */
193 void remove(Optional<BlankNodeOrIRI> graphName, BlankNodeOrIRI subject, IRI predicate, RDFTerm object);
194
195 /**
196 * Clear the dataset, removing all quads.
197 */
198 @Override
199 void clear();
200
201 /**
202 * Number of quads contained by the dataset.
203 * <p>
204 * The count of a set does not include duplicates, consistent with the
205 * {@link Quad#equals(Object)} equals method for each {@link Quad}.
206 *
207 * @return The number of quads in the dataset
208 */
209 @Override
210 long size();
211
212 /**
213 * Get all quads contained by the dataset.<br>
214 * <p>
215 * The iteration does not contain any duplicate quads, as determined by the
216 * {@link Quad#equals(Object)} method for each {@link Quad}.
217 * <p>
218 * The behaviour of the {@link Stream} is not specified if
219 * {@link #add(Quad)}, {@link #remove(Quad)} or {@link #clear()} are called
220 * on the {@link Dataset} before it terminates.
221 * <p>
222 * Implementations may throw {@link ConcurrentModificationException} from
223 * Stream methods if they detect a conflict while the Stream is active.
224 *
225 * @return A {@link Stream} over all of the quads in the dataset
226 */
227 @Override
228 Stream<? extends Quad> stream();
229
230 /**
231 * Get all quads contained by the dataset matched with the pattern.
232 * <p>
233 * The iteration does not contain any duplicate quads, as determined by the
234 * {@link Quad#equals(Object)} method for each {@link Quad}.
235 * <p>
236 * The behaviour of the {@link Stream} is not specified if
237 * {@link #add(Quad)}, {@link #remove(Quad)} or {@link #clear()} are called
238 * on the {@link Dataset} before it terminates.
239 * <p>
240 * Implementations may throw {@link ConcurrentModificationException} from
241 * Stream methods if they detect a conflict while the Stream is active.
242 *
243 * @param graphName
244 * The graph the quad belongs to, wrapped as an {@link Optional}
245 * (<code>null</code> is a wildcard, {@link Optional#empty()} is
246 * the default graph)
247 * @param subject
248 * The quad subject (<code>null</code> is a wildcard)
249 * @param predicate
250 * The quad predicate (<code>null</code> is a wildcard)
251 * @param object
252 * The quad object (<code>null</code> is a wildcard)
253 * @return A {@link Stream} over the matched quads.
254 */
255 Stream<? extends Quad> stream(Optional<BlankNodeOrIRI> graphName, BlankNodeOrIRI subject, IRI predicate,
256 RDFTerm object);
257
258 /**
259 * Get an Iterable for iterating over all quads in the dataset.
260 * <p>
261 * This method is meant to be used with a Java for-each loop, e.g.:
262 *
263 * <pre>
264 * for (Quad t : dataset.iterate()) {
265 * System.out.println(t);
266 * }
267 * </pre>
268 *
269 * The behaviour of the iterator is not specified if {@link #add(Quad)},
270 * {@link #remove(Quad)} or {@link #clear()}, are called on the
271 * {@link Dataset} before it terminates. It is undefined if the returned
272 * {@link Iterator} supports the {@link Iterator#remove()} method.
273 * <p>
274 * Implementations may throw {@link ConcurrentModificationException} from
275 * Iterator methods if they detect a concurrency conflict while the Iterator
276 * is active.
277 * <p>
278 * The {@link Iterable#iterator()} must only be called once, that is the
279 * Iterable must only be iterated over once. A {@link IllegalStateException}
280 * may be thrown on attempt to reuse the Iterable.
281 * <p>
282 * The default implementation of this method will call {@link #stream()} to
283 * return its {@link Stream#iterator()}.
284 *
285 * @return A {@link Iterable} that returns {@link Iterator} over all of the
286 * quads in the dataset
287 * @throws IllegalStateException
288 * if the {@link Iterable} has been reused
289 * @throws ConcurrentModificationException
290 * if a concurrency conflict occurs while the Iterator is
291 * active.
292 */
293 @Override
294 @SuppressWarnings("unchecked")
295 default Iterable<Quad> iterate() throws ConcurrentModificationException, IllegalStateException {
296 return ((Stream<Quad>) stream())::iterator;
297 }
298
299 /**
300 * Get an Iterable for iterating over the quads in the dataset that match
301 * the pattern.
302 * <p>
303 * This method is meant to be used with a Java for-each loop, e.g.:
304 *
305 * <pre>
306 * IRI alice = factory.createIRI("http://example.com/alice");
307 * IRI knows = factory.createIRI("http://xmlns.com/foaf/0.1/");
308 * for (Quad t : dataset.iterate(null, alice, knows, null)) {
309 * System.out.println(t.getGraphName());
310 * System.out.println(t.getObject());
311 * }
312 * </pre>
313 * <p>
314 * The behaviour of the iterator is not specified if {@link #add(Quad)},
315 * {@link #remove(Quad)} or {@link #clear()}, are called on the
316 * {@link Dataset} before it terminates. It is undefined if the returned
317 * {@link Iterator} supports the {@link Iterator#remove()} method.
318 * <p>
319 * Implementations may throw {@link ConcurrentModificationException} from
320 * Iterator methods if they detect a concurrency conflict while the Iterator
321 * is active.
322 * <p>
323 * The {@link Iterable#iterator()} must only be called once, that is the
324 * Iterable must only be iterated over once. A {@link IllegalStateException}
325 * may be thrown on attempt to reuse the Iterable.
326 * <p>
327 * The default implementation of this method will call
328 * {@link #stream(Optional, BlankNodeOrIRI, IRI, RDFTerm)} to return its
329 * {@link Stream#iterator()}.
330 *
331 * @param graphName
332 * The graph the quad belongs to, wrapped as an {@link Optional}
333 * (<code>null</code> is a wildcard, {@link Optional#empty()} is
334 * the default graph)
335 * @param subject
336 * The quad subject (<code>null</code> is a wildcard)
337 * @param predicate
338 * The quad predicate (<code>null</code> is a wildcard)
339 * @param object
340 * The quad object (<code>null</code> is a wildcard)
341 * @return A {@link Iterable} that returns {@link Iterator} over the
342 * matching quads in the dataset
343 * @throws IllegalStateException
344 * if the {@link Iterable} has been reused
345 * @throws ConcurrentModificationException
346 * if a concurrency conflict occurs while the Iterator is
347 * active.
348 */
349 @SuppressWarnings("unchecked")
350 default Iterable<Quad> iterate(final Optional<BlankNodeOrIRI> graphName, final BlankNodeOrIRI subject, final IRI predicate,
351 final RDFTerm object) throws ConcurrentModificationException, IllegalStateException {
352 return ((Stream<Quad>) stream(graphName, subject, predicate, object))::iterator;
353 }
354 }