001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.commons.rdf.api;
019
020import java.util.ConcurrentModificationException;
021import java.util.Iterator;
022import java.util.Optional;
023import java.util.stream.Stream;
024
025/**
026 * An <a href="http://www.w3.org/TR/rdf11-concepts/#dfn-rdf-dataset">RDF
027 * 1.1 Dataset</a>, a set of RDF quads, as defined by
028 * <a href="http://www.w3.org/TR/rdf11-concepts/#section-rdf-dataset">RDF-1.1 Concepts and Abstract
029 * Syntax</a>, a W3C Recommendation published on 25 February 2014.
030 *
031 * @since 0.3.0-incubating
032 * @see RDF#createDataset()
033 */
034public interface Dataset extends AutoCloseable, GraphLike<Quad> {
035
036    /**
037     * Add a quad to the dataset, possibly mapping any of the components of the
038     * Quad to those supported by this dataset.
039     *
040     * @param quad
041     *            The quad to add
042     */
043    @Override
044    void add(Quad quad);
045
046    /**
047     * Add a quad to the dataset, possibly mapping any of the components to
048     * those supported by this dataset.
049     *
050     * @param graphName
051     *            The graph the quad belongs to, or <code>null</code> for the
052     *            default graph
053     * @param subject
054     *            The quad subject
055     * @param predicate
056     *            The quad predicate
057     * @param object
058     *            The quad object
059     */
060    void add(BlankNodeOrIRI graphName, BlankNodeOrIRI subject, IRI predicate, RDFTerm object);
061
062    /**
063     * Check if dataset contains quad.
064     *
065     * @param quad
066     *            The quad to check.
067     * @return True if the dataset contains the given Quad.
068     */
069    @Override
070    boolean contains(Quad quad);
071
072    /**
073     * Check if dataset contains a pattern of quads.
074     *
075     * @param graphName
076     *            The graph the quad belongs to, wrapped as an {@link Optional}
077     *            (<code>null</code> is a wildcard, {@link Optional#empty()} is
078     *            the default graph)
079     * @param subject
080     *            The quad subject (<code>null</code> is a wildcard)
081     * @param predicate
082     *            The quad predicate (<code>null</code> is a wildcard)
083     * @param object
084     *            The quad object (<code>null</code> is a wildcard)
085     * @return True if the dataset contains any quads that match the given
086     *         pattern.
087     */
088    boolean contains(Optional<BlankNodeOrIRI> graphName, BlankNodeOrIRI subject, IRI predicate, RDFTerm object);
089
090    /**
091     * Close the dataset, relinquishing any underlying resources.
092     * <p>
093     * For example, this would close any open file and network streams and free
094     * database locks held by the dataset implementation.
095     * <p>
096     * The behaviour of the other dataset methods are undefined after closing
097     * the dataset.
098     * <p>
099     * 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}