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}