package eu.ehri.project.indexing.source.impl;
import eu.ehri.project.indexing.source.Source;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayDeque;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Queue;
/**
* Aggregate multiple sources into one.
*/
public class MultiSource<T, S extends Source<? extends T>> implements Source<T> {
private final static Logger logger = LoggerFactory.getLogger(MultiSource.class);
private final List<S> sources;
private boolean finished = false;
private S currentSource = null;
private Iterator<? extends T> currentSourceIterator = null;
public MultiSource(List<S> sources) {
this.sources = sources;
}
@Override
public void close() throws SourceException {
finished = true;
logger.trace("Finish");
}
@Override
public Iterable<T> iterable() throws SourceException {
final Queue<S> sourceQueue = new ArrayDeque<>(sources);
return new Iterable<T>() {
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private boolean getNextValidIterator() {
try {
while (!sourceQueue.isEmpty()) {
if (currentSource != null) {
currentSource.close();
}
currentSource = sourceQueue.remove();
currentSourceIterator = currentSource.iterable().iterator();
if (currentSourceIterator.hasNext()) {
return true;
}
}
if (currentSource != null) {
currentSource.close();
}
return false;
} catch (SourceException e) {
throw new RuntimeException(e);
}
}
@Override
public boolean hasNext() {
if (currentSourceIterator != null) {
return currentSourceIterator.hasNext() || getNextValidIterator();
} else {
return getNextValidIterator();
}
}
@Override
public T next() {
if (!hasNext()) throw new NoSuchElementException();
return currentSourceIterator.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
};
}
@Override
public boolean isFinished() {
return finished;
}
}