Skip to content

Commit 5a53de4

Browse files
bern-soptimarne-bdt
authored andcommitted
GH-3969: Native stream() implementations for DatasetGraph
Replace the find()-wrapping default of DatasetGraph.stream(g,s,p,o) with first-class stream support across the hierarchy. DatasetGraphBaseFind gets a stream() path mirroring the find() default-/named-/union-graph split, backed by streamInDftGraph / streamInSpecificNamedGraph / streamInAnyNamedGraphs primitives implemented per dataset. GraphView streams graph-over-dataset through DatasetGraph#stream; adds G stream helpers. The interface method stays default, so implementors are not broken. Includes stream()==find() parity tests and a forEachRemaining check in IteratorTxnTracker so stream bulk operations stay inside their transaction.
1 parent 348d869 commit 5a53de4

25 files changed

Lines changed: 667 additions & 13 deletions

File tree

jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/DatasetGraphOrdered.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import java.util.Iterator;
2525
import java.util.LinkedHashSet;
26+
import java.util.stream.Stream;
2627

2728
import org.apache.jena.atlas.iterator.Iter;
2829
import org.apache.jena.graph.Graph;
@@ -65,6 +66,16 @@ public Iterator<Quad> findNG(Node g, Node s, Node p, Node o) {
6566
return iterator;
6667
}
6768

69+
@Override
70+
public Stream<Quad> stream(Node g, Node s, Node p, Node o) {
71+
return quads.stream().filter(quad -> matches(quad, g, s, p, o));
72+
}
73+
74+
@Override
75+
public Stream<Quad> stream() {
76+
return quads.stream();
77+
}
78+
6879
@Override
6980
public void add(Quad quad) {
7081
quads.add(quad);

jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphBaseFind.java

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,46 @@ protected Iterator<Quad> findAny(Node s, Node p, Node o) {
8282
return Iter.append(iter1, iter2);
8383
}
8484

85+
@Override
86+
public Stream<Quad> stream(Node g, Node s, Node p, Node o) {
87+
if ( Quad.isDefaultGraph(g))
88+
return streamInDftGraph(s, p, o) ;
89+
if ( ! isWildcard(g) )
90+
return streamNG(g, s, p, o) ;
91+
return streamAny(s, p, o) ;
92+
}
93+
94+
/** Stream equivalent of {@link #findNG(Node, Node, Node, Node)}. */
95+
public Stream<Quad> streamNG(Node g, Node s, Node p , Node o) {
96+
Stream<Quad> stream ;
97+
if ( Quad.isUnionGraph(g))
98+
stream = streamQuadsInUnionGraph(s, p, o) ;
99+
else if ( isWildcard(g) )
100+
stream = streamInAnyNamedGraphs(s, p, o) ;
101+
else if ( Quad.isDefaultGraph(g) )
102+
stream = streamInDftGraph(s, p, o) ;
103+
else
104+
// Not wildcard, not union graph, not default graph.
105+
stream = streamInSpecificNamedGraph(g, s, p, o) ;
106+
if ( stream == null )
107+
return Stream.empty() ;
108+
return stream ;
109+
}
110+
111+
protected Stream<Quad> streamAny(Node s, Node p, Node o) {
112+
return Stream.concat(streamInDftGraph(s, p, o), streamInAnyNamedGraphs(s, p, o)) ;
113+
}
114+
85115
/** Find matches in the default graph.
86116
* Return as quads; the default graph is {@link Quad#defaultGraphIRI}
87117
* To get Triples, use {@code DatasetGraph.getDefaultGraph().find(...)}.
88118
*/
89119
protected abstract Iterator<Quad> findInDftGraph(Node s, Node p , Node o) ;
90120

121+
/** Stream equivalent of {@link #findInDftGraph}.
122+
*/
123+
protected abstract Stream<Quad> streamInDftGraph(Node s, Node p, Node o) ;
124+
91125
/** Find matches in the notional union of all named graphs - return as triples.
92126
* No duplicates - the union graph is a <em>set</em> of triples.
93127
* See {@link #findInAnyNamedGraphs}, where there may be duplicates.
@@ -110,6 +144,11 @@ public Iterator<Quad> findQuadsInUnionGraph(Node s, Node p , Node o) {
110144
return findUnionGraphTriples(s,p,o).map(t -> Quad.create(Quad.unionGraph, t)).iterator() ;
111145
}
112146

147+
/** Stream equivalent of {@link #findQuadsInUnionGraph}. */
148+
public Stream<Quad> streamQuadsInUnionGraph(Node s, Node p , Node o) {
149+
return findUnionGraphTriples(s,p,o).map(t -> Quad.create(Quad.unionGraph, t)) ;
150+
}
151+
113152
/** Find matches in the notional union of all named graphs - return as triples.
114153
* No duplicates - the union graph is a <em>set</em> of triples.
115154
* See {@link #findInAnyNamedGraphs}, where there may be duplicates.
@@ -118,15 +157,21 @@ public Iterator<Quad> findQuadsInUnionGraph(Node s, Node p , Node o) {
118157
* may be possible to avoid "distinct".
119158
*/
120159
private Stream<Triple> findUnionGraphTriples(Node s, Node p , Node o) {
121-
return Iter.asStream(findInAnyNamedGraphs(s,p,o)).map(Quad::asTriple).distinct() ;
160+
return streamInAnyNamedGraphs(s,p,o).map(Quad::asTriple).distinct() ;
122161
}
123162

124163
/** Find in a specific named graph - {@code g} is a ground term (IRI or bNode), not a wild card (or null). */
125164
protected abstract Iterator<Quad> findInSpecificNamedGraph(Node g, Node s, Node p , Node o) ;
126165

166+
/** Stream equivalent of {@link #findInSpecificNamedGraph}. */
167+
protected abstract Stream<Quad> streamInSpecificNamedGraph(Node g, Node s, Node p, Node o) ;
168+
127169
/** Find in any named graph - return quads.
128170
* If a triple matches in two different graph, return a quad for each.
129171
* See {@link #findInUnionGraph} for matching without duplicate triples.
130172
*/
131173
protected abstract Iterator<Quad> findInAnyNamedGraphs(Node s, Node p , Node o) ;
174+
175+
/** Stream equivalent of {@link #findInAnyNamedGraphs}. */
176+
protected abstract Stream<Quad> streamInAnyNamedGraphs(Node s, Node p, Node o) ;
132177
}

jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphCollection.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.Iterator ;
2525
import java.util.List ;
2626
import java.util.Objects ;
27+
import java.util.stream.Stream;
2728

2829
import org.apache.jena.atlas.iterator.Iter ;
2930
import org.apache.jena.atlas.iterator.IteratorConcat ;
@@ -63,6 +64,11 @@ protected Iterator<Quad> findInDftGraph(Node s, Node p , Node o)
6364
return G.triples2quadsDftGraph(getDefaultGraph().find(s, p, o)) ;
6465
}
6566

67+
@Override
68+
protected Stream<Quad> streamInDftGraph(Node s, Node p, Node o) {
69+
return G.triples2quadsDftGraph(getDefaultGraph().stream(s, p, o)) ;
70+
}
71+
6672
@Override
6773
protected Iter<Quad> findInSpecificNamedGraph(Node g, Node s, Node p , Node o)
6874
{
@@ -72,6 +78,14 @@ protected Iter<Quad> findInSpecificNamedGraph(Node g, Node s, Node p , Node o)
7278
return G.triples2quads(g, graph.find(s, p, o)) ;
7379
}
7480

81+
@Override
82+
protected Stream<Quad> streamInSpecificNamedGraph(Node g, Node s, Node p, Node o) {
83+
Graph graph = fetchGraph(g) ;
84+
if ( graph == null )
85+
return Stream.empty() ;
86+
return G.triples2quads(g, graph.stream(s, p, o)) ;
87+
}
88+
7589
@Override
7690
protected Iterator<Quad> findInAnyNamedGraphs(Node s, Node p, Node o)
7791
{
@@ -89,6 +103,12 @@ protected Iterator<Quad> findInAnyNamedGraphs(Node s, Node p, Node o)
89103
return iter ;
90104
}
91105

106+
@Override
107+
protected Stream<Quad> streamInAnyNamedGraphs(Node s, Node p, Node o) {
108+
return Iter.asStream(listGraphNodes())
109+
.flatMap(gn -> streamInSpecificNamedGraph(gn, s, p, o));
110+
}
111+
92112
@Override
93113
public abstract Iterator<Node> listGraphNodes() ;
94114

jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphFilteredView.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import java.util.HashSet;
2626
import java.util.Iterator;
2727
import java.util.function.Predicate;
28+
import java.util.stream.Stream;
2829

2930
import org.apache.jena.atlas.iterator.Iter;
3031
import org.apache.jena.atlas.logging.Log;
@@ -90,6 +91,12 @@ private Iterator<Quad> filter(Iterator<Quad> iter) {
9091
return iter;
9192
return Iter.filter(iter, this::filter);
9293
}
94+
95+
private Stream<Quad> filter(Stream<Quad> stream) {
96+
if ( this.quadFilter == null )
97+
return stream;
98+
return stream.filter(this::filter);
99+
}
93100

94101
// Need to intercept these because otherwise that are a GraphView of the wrapped "dsg", not this one.
95102

@@ -149,6 +156,14 @@ public Iterator<Quad> find() {
149156
return filter(super.find(g, s, p, o)).hasNext();
150157
}
151158

159+
@Override public Stream<Quad> stream(Node g, Node s, Node p, Node o) {
160+
return filter(super.stream(g, s, p, o));
161+
}
162+
163+
@Override public Stream<Quad> stream() {
164+
return filter(super.stream());
165+
}
166+
152167
@Override public boolean contains(Quad quad) {
153168
return filter(super.find(quad)).hasNext();
154169
}

jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphMap.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
import java.util.Map;
2727
import java.util.Map.Entry;
2828
import java.util.Objects;
29+
import java.util.stream.Stream;
2930

31+
import org.apache.jena.atlas.iterator.Iter;
3032
import org.apache.jena.atlas.iterator.IteratorConcat;
3133
import org.apache.jena.graph.Graph;
3234
import org.apache.jena.graph.Node;
@@ -157,12 +159,22 @@ protected Iterator<Quad> findInDftGraph(Node s, Node p, Node o) {
157159
return G.triples2quadsDftGraph(iter) ;
158160
}
159161

162+
@Override
163+
protected Stream<Quad> streamInDftGraph(Node s, Node p, Node o) {
164+
return G.triples2quadsDftGraph(getDefaultGraph().stream(s, p, o));
165+
}
166+
160167
@Override
161168
protected Iterator<Quad> findInSpecificNamedGraph(Node g, Node s, Node p, Node o) {
162169
Iterator<Triple> iter = getGraph(g).find(s, p, o);
163170
return G.triples2quads(g, iter);
164171
}
165172

173+
@Override
174+
protected Stream<Quad> streamInSpecificNamedGraph(Node g, Node s, Node p, Node o) {
175+
return G.triples2quads(g, getGraph(g).stream(s, p, o));
176+
}
177+
166178
@Override
167179
protected Iterator<Quad> findInAnyNamedGraphs(Node s, Node p, Node o) {
168180
Iterator<Node> gnames = listGraphNodes();
@@ -178,6 +190,12 @@ protected Iterator<Quad> findInAnyNamedGraphs(Node s, Node p, Node o) {
178190
return iter;
179191
}
180192

193+
@Override
194+
protected Stream<Quad> streamInAnyNamedGraphs(Node s, Node p, Node o) {
195+
return Iter.asStream(listGraphNodes())
196+
.flatMap(gn -> streamInSpecificNamedGraph(gn, s, p, o));
197+
}
198+
181199
@Override
182200
public Graph getDefaultGraph() {
183201
return defaultGraph;

jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphNull.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
package org.apache.jena.sparql.core;
2323

2424
import java.util.Iterator;
25+
import java.util.stream.Stream;
2526

2627
import org.apache.jena.atlas.iterator.Iter;
2728
import org.apache.jena.graph.Graph;
@@ -73,16 +74,31 @@ protected Iterator<Quad> findInDftGraph(Node s, Node p, Node o) {
7374
return Iter.nullIterator();
7475
}
7576

77+
@Override
78+
protected Stream<Quad> streamInDftGraph(Node s, Node p, Node o) {
79+
return Stream.empty();
80+
}
81+
7682
@Override
7783
protected Iterator<Quad> findInSpecificNamedGraph(Node g, Node s, Node p, Node o) {
7884
return Iter.nullIterator();
7985
}
8086

87+
@Override
88+
protected Stream<Quad> streamInSpecificNamedGraph(Node g, Node s, Node p, Node o) {
89+
return Stream.empty();
90+
}
91+
8192
@Override
8293
protected Iterator<Quad> findInAnyNamedGraphs(Node s, Node p, Node o) {
8394
return Iter.nullIterator();
8495
}
8596

97+
@Override
98+
protected Stream<Quad> streamInAnyNamedGraphs(Node s, Node p, Node o) {
99+
return Stream.empty();
100+
}
101+
86102
@Override
87103
public Graph getDefaultGraph() {
88104
return dftGraph;

jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphOne.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
package org.apache.jena.sparql.core;
2323

2424
import java.util.Iterator;
25+
import java.util.stream.Stream;
2526

2627
import org.apache.jena.atlas.iterator.Iter;
2728
import org.apache.jena.graph.Graph;
@@ -202,18 +203,35 @@ protected Iterator<Quad> findInDftGraph(Node s, Node p, Node o) {
202203
return G.triples2quadsDftGraph(graph.find(s, p, o));
203204
}
204205

206+
@Override
207+
protected Stream<Quad> streamInDftGraph(Node s, Node p, Node o) {
208+
return G.triples2quadsDftGraph(graph.stream(s, p, o));
209+
}
210+
205211
@Override
206212
protected Iterator<Quad> findInSpecificNamedGraph(Node g, Node s, Node p, Node o) {
207213
// There are no named graphs
208214
return Iter.nullIterator();
209215
}
210216

217+
@Override
218+
protected Stream<Quad> streamInSpecificNamedGraph(Node g, Node s, Node p, Node o) {
219+
// There are no named graphs
220+
return Stream.empty();
221+
}
222+
211223
@Override
212224
protected Iterator<Quad> findInAnyNamedGraphs(Node s, Node p, Node o) {
213225
// There are no named graphs
214226
return Iter.nullIterator();
215227
}
216228

229+
@Override
230+
protected Stream<Quad> streamInAnyNamedGraphs(Node s, Node p, Node o) {
231+
// There are no named graphs
232+
return Stream.empty();
233+
}
234+
217235
protected static boolean isDefaultGraph(Quad quad) {
218236
return isDefaultGraph(quad.getGraph());
219237
}

jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphWrapper.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
package org.apache.jena.sparql.core;
2323

2424
import java.util.Iterator;
25+
import java.util.stream.Stream;
2526

2627
import org.apache.jena.atlas.lib.Sync;
2728
import org.apache.jena.graph.Graph;
@@ -211,6 +212,14 @@ public Iterator<Quad> find(Node g, Node s, Node p, Node o)
211212
public Iterator<Quad> findNG(Node g, Node s, Node p, Node o)
212213
{ return getR().findNG(g, s, p, o); }
213214

215+
@Override
216+
public Stream<Quad> stream(Node g, Node s, Node p, Node o)
217+
{ return getR().stream(g, s, p, o); }
218+
219+
@Override
220+
public Stream<Quad> stream()
221+
{ return getR().stream(); }
222+
214223
@Override
215224
public boolean contains(Quad quad)
216225
{ return getR().contains(quad); }

jena-arq/src/main/java/org/apache/jena/sparql/core/GraphView.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
package org.apache.jena.sparql.core;
2323

2424
import java.util.Iterator ;
25+
import java.util.stream.Stream;
2526

2627
import org.apache.jena.atlas.iterator.Iter ;
2728
import org.apache.jena.atlas.lib.Sync ;
@@ -125,6 +126,24 @@ protected ExtendedIterator<Triple> graphBaseFind(Node s, Node p, Node o) {
125126
return WrappedIterator.createNoRemove(iter) ;
126127
}
127128

129+
/**
130+
* Stream equivalent of {@link #graphBaseFind} / {@link #graphUnionFind}: route through DatasetGraph#stream
131+
* so stream-native dataset (e.g. an in-memory one) stays on streams rather than iterator-wrapping.
132+
* @param s subject match
133+
* @param p predicate match
134+
* @param o object match
135+
* @return stream of matching triples
136+
*/
137+
@Override
138+
public Stream<Triple> stream(Node s, Node p, Node o) {
139+
Node g = graphNode(graphName) ;
140+
Stream<Triple> stream = G.quads2triples(dsg.stream(g, s, p, o)) ;
141+
if ( Quad.isUnionGraph(graphName) )
142+
// Suppress duplicates after projecting to triples.
143+
stream = stream.distinct() ;
144+
return stream ;
145+
}
146+
128147
private static Node graphNode(Node gn) {
129148
return ( gn == null ) ? Quad.defaultGraphNodeGenerated : gn ;
130149
}

0 commit comments

Comments
 (0)