UnionIteration.java
/*******************************************************************************
* Copyright (c) 2015 Eclipse RDF4J contributors, Aduna, and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Distribution License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
package org.eclipse.rdf4j.common.iteration;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* An Iteration that returns the bag union of the results of a number of Iterations. 'Bag union' means that the
* UnionIteration does not filter duplicate objects.
*/
public class UnionIteration<E> extends LookAheadIteration<E> {
/*-----------*
* Variables *
*-----------*/
private final Iterator<? extends CloseableIteration<? extends E>> argIter;
private CloseableIteration<? extends E> currentIter;
/*--------------*
* Constructors *
*--------------*/
/**
* Creates a new UnionIteration that returns the bag union of the results of a number of Iterations.
*
* @param args The Iterations containing the elements to iterate over.
*/
@SafeVarargs
public UnionIteration(CloseableIteration<? extends E>... args) {
this(Arrays.asList(args));
}
/**
* Creates a new UnionIteration that returns the bag union of the results of a number of Iterations.
*
* @param args The Iterations containing the elements to iterate over.
*/
public UnionIteration(Iterable<? extends CloseableIteration<? extends E>> args) {
argIter = args.iterator();
// Initialize with empty iteration
currentIter = new EmptyIteration<>();
}
/*--------------*
* Constructors *
*--------------*/
@Override
protected E getNextElement() {
if (isClosed()) {
return null;
}
while (true) {
CloseableIteration<? extends E> nextCurrentIter = currentIter;
if (nextCurrentIter != null && nextCurrentIter.hasNext()) {
return nextCurrentIter.next();
}
// Current Iteration exhausted, continue with the next one
if (nextCurrentIter != null) {
nextCurrentIter.close();
}
if (argIter.hasNext()) {
currentIter = argIter.next();
} else {
// All elements have been returned
return null;
}
}
}
@Override
protected void handleClose() {
try {
List<Throwable> collectedExceptions = new ArrayList<>();
while (argIter.hasNext()) {
try {
CloseableIteration<? extends E> next = argIter.next();
if (next != null) {
next.close();
}
} catch (Throwable e) {
collectedExceptions.add(e);
}
}
if (!collectedExceptions.isEmpty()) {
throw new UndeclaredThrowableException(collectedExceptions.get(0));
}
} finally {
if (currentIter != null) {
currentIter.close();
}
}
}
}