1313import static org .eclipse .rdf4j .sail .nativerdf .NativeStore .SOFT_FAIL_ON_CORRUPT_DATA_AND_REPAIR_INDEXES ;
1414
1515import java .io .IOException ;
16+ import java .util .NoSuchElementException ;
1617
1718import org .eclipse .rdf4j .common .io .ByteArrayUtil ;
18- import org .eclipse .rdf4j .common .iteration .LookAheadIteration ;
19+ import org .eclipse .rdf4j .common .iteration .CloseableIteration ;
1920import org .eclipse .rdf4j .model .IRI ;
2021import org .eclipse .rdf4j .model .Resource ;
2122import org .eclipse .rdf4j .model .Statement ;
3233 * A statement iterator that wraps a RecordIterator containing statement records and translates these records to
3334 * {@link Statement} objects.
3435 */
35- class NativeStatementIterator extends LookAheadIteration <Statement > {
36+ class NativeStatementIterator implements CloseableIteration <Statement > {
3637
3738 private static final Logger logger = LoggerFactory .getLogger (NativeStatementIterator .class );
3839
39- /*-----------*
40- * Variables *
41- *-----------*/
42-
4340 private final RecordIterator btreeIter ;
44-
4541 private final ValueStore valueStore ;
4642
47- /*--------------*
48- * Constructors *
49- *--------------*/
43+ private Statement nextElement ;
44+ private boolean closed = false ;
5045
51- /**
52- * Creates a new NativeStatementIterator.
53- */
5446 public NativeStatementIterator (RecordIterator btreeIter , ValueStore valueStore ) {
5547 this .btreeIter = btreeIter ;
5648 this .valueStore = valueStore ;
5749 }
5850
59- /*---------*
60- * Methods *
61- *---------*/
62-
63- @ Override
6451 public Statement getNextElement () throws SailException {
6552 try {
6653 byte [] nextValue ;
@@ -107,7 +94,6 @@ public Statement getNextElement() throws SailException {
10794 }
10895 }
10996
110- @ Override
11197 protected void handleClose () throws SailException {
11298 try {
11399 btreeIter .close ();
@@ -119,4 +105,79 @@ protected void handleClose() throws SailException {
119105 protected SailException causeIOException (IOException e ) {
120106 return new SailException (e );
121107 }
108+
109+ @ Override
110+ public final boolean hasNext () {
111+ if (isClosed ()) {
112+ return false ;
113+ }
114+
115+ try {
116+ return lookAhead () != null ;
117+ } catch (NoSuchElementException logged ) {
118+ // The lookAhead() method shouldn't throw a NoSuchElementException since it should return null when there
119+ // are no more elements.
120+ logger .trace ("LookAheadIteration threw NoSuchElementException:" , logged );
121+ return false ;
122+ }
123+ }
124+
125+ @ Override
126+ public final Statement next () {
127+ if (isClosed ()) {
128+ throw new NoSuchElementException ("The iteration has been closed." );
129+ }
130+ Statement result = lookAhead ();
131+
132+ if (result != null ) {
133+ nextElement = null ;
134+ return result ;
135+ } else {
136+ throw new NoSuchElementException ();
137+ }
138+ }
139+
140+ /**
141+ * Fetches the next element if it hasn't been fetched yet and stores it in {@link #nextElement}.
142+ *
143+ * @return The next element, or null if there are no more results.
144+ */
145+ private Statement lookAhead () {
146+ if (nextElement == null ) {
147+ nextElement = getNextElement ();
148+
149+ if (nextElement == null ) {
150+ close ();
151+ }
152+ }
153+ return nextElement ;
154+ }
155+
156+ /**
157+ * Throws an {@link UnsupportedOperationException}.
158+ */
159+ @ Override
160+ public void remove () {
161+ throw new UnsupportedOperationException ();
162+ }
163+
164+ /**
165+ * Checks whether this CloseableIteration has been closed.
166+ *
167+ * @return <var>true</var> if the CloseableIteration has been closed, <var>false</var> otherwise.
168+ */
169+ public final boolean isClosed () {
170+ return closed ;
171+ }
172+
173+ /**
174+ * Calls {@link #handleClose()} upon first call and makes sure the resource closures are only executed once.
175+ */
176+ @ Override
177+ public final void close () {
178+ if (!closed ) {
179+ closed = true ;
180+ handleClose ();
181+ }
182+ }
122183}
0 commit comments