/**
* 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.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;
import org.roda.core.storage.Binary;
import org.roda.core.storage.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LogEntryStorageIterable implements CloseableIterable<OptionalWithCause<LogEntry>> {
private static final Logger LOGGER = LoggerFactory.getLogger(LogEntryStorageIterable.class);
private final class LogEntryIterator implements Iterator<OptionalWithCause<LogEntry>> {
private final Iterator<Resource> resources;
private OptionalWithCause<LogEntry> next = null;
private BufferedReader br = null;
public LogEntryIterator(Iterator<Resource> resources) {
this.resources = resources;
}
private boolean forwardNextFile() {
boolean foundIt = false;
while (resources.hasNext()) {
Resource resource = resources.next();
if (resource instanceof Binary) {
Binary b = (Binary) resource;
LOGGER.debug("Processing log file: {}", b.getStoragePath());
try {
IOUtils.closeQuietly(br);
// input stream is closed by the buffer
br = new BufferedReader(new InputStreamReader(b.getContent().createInputStream()));
if (forwardInFile()) {
foundIt = true;
break;
}
} catch (IOException e) {
LOGGER.debug("Error loading log entry", e);
foundIt = true;
next = OptionalWithCause.empty(new GenericException(e));
}
}
}
if (!foundIt) {
next = null;
}
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) {
LOGGER.debug("Error loading log entry", e);
next = OptionalWithCause.empty(e);
foundIt = true;
} catch (IOException e) {
LOGGER.debug("Error loading log entry", 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 CloseableIterable<Resource> actionLogs;
public LogEntryStorageIterable(CloseableIterable<Resource> actionLogs) {
this.actionLogs = actionLogs;
}
@Override
public void close() throws IOException {
actionLogs.close();
}
@Override
public Iterator<OptionalWithCause<LogEntry>> iterator() {
return new LogEntryIterator(actionLogs.iterator());
}
}