/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE file at the root of the source
* tree and available online at
*
* https://github.com/keeps/roda
*/
package org.roda.core.model.iterables;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.DirectoryStream;
import java.nio.file.DirectoryStream.Filter;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.NoSuchElementException;
import org.apache.commons.io.IOUtils;
import org.roda.core.common.iterables.CloseableIterable;
import org.roda.core.data.exceptions.GenericException;
import org.roda.core.data.utils.JsonUtils;
import org.roda.core.data.v2.common.OptionalWithCause;
import org.roda.core.data.v2.log.LogEntry;
public class LogEntryFileSystemIterable implements CloseableIterable<OptionalWithCause<LogEntry>> {
private final class LogEntryIterator implements Iterator<OptionalWithCause<LogEntry>> {
private final Iterator<Path> paths;
private BufferedReader br = null;
private OptionalWithCause<LogEntry> next = null;
public LogEntryIterator(Iterator<Path> paths) {
this.paths = paths;
}
private boolean forwardNextFile() {
boolean foundIt = false;
while (paths.hasNext()) {
Path logFile = paths.next();
try {
IOUtils.closeQuietly(br);
// input stream is closed by the buffer
br = new BufferedReader(new InputStreamReader(Files.newInputStream(logFile)));
if (forwardInFile()) {
foundIt = true;
break;
}
} catch (IOException e) {
foundIt = true;
next = OptionalWithCause.empty(new GenericException(e));
}
}
if (!foundIt) {
next = null;
IOUtils.closeQuietly(br);
}
return foundIt;
}
private boolean forwardInFile() {
boolean foundIt = false;
try {
String nextLine = br.readLine();
if (nextLine != null) {
next = OptionalWithCause.of(JsonUtils.getObjectFromJson(nextLine, LogEntry.class));
foundIt = true;
}
} catch (GenericException e) {
next = OptionalWithCause.empty(e);
foundIt = true;
} catch (IOException e) {
next = OptionalWithCause.empty(new GenericException(e));
foundIt = true;
}
return foundIt;
}
@Override
public boolean hasNext() {
if (next == null) {
forwardNextFile();
}
return next != null;
}
@Override
public OptionalWithCause<LogEntry> next() {
OptionalWithCause<LogEntry> ret;
if (next != null) {
ret = next;
if (!forwardInFile()) {
forwardNextFile();
}
} else {
throw new NoSuchElementException();
}
return ret;
}
}
private final DirectoryStream<Path> directoryStream;
public LogEntryFileSystemIterable(Path logPath) throws IOException {
this.directoryStream = Files.newDirectoryStream(logPath);
}
public LogEntryFileSystemIterable(Path logPath, Filter<? super Path> filter) throws IOException {
this.directoryStream = Files.newDirectoryStream(logPath, filter);
}
@Override
public void close() throws IOException {
directoryStream.close();
}
@Override
public Iterator<OptionalWithCause<LogEntry>> iterator() {
Iterator<Path> paths = directoryStream.iterator();
return new LogEntryIterator(paths);
}
}