Skip to content

Instantly share code, notes, and snippets.

@skiwi2
Created January 16, 2015 18:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save skiwi2/d6e68f8dee55c2288244 to your computer and use it in GitHub Desktop.
Save skiwi2/d6e68f8dee55c2288244 to your computer and use it in GitHub Desktop.
package com.github.skiwi2.hearthmonitor.logreader;
import com.github.skiwi2.hearthmonitor.logapi.LogEntry;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;
import java.util.function.Predicate;
/**
* Can be extended to read lines from a log source.
*
* @author Frank van Heeswijk
*/
public abstract class AbstractLogReader implements LogReader {
private final Set<EntryParser> entryParsers;
private final Iterator<String> readIterator;
private final List<String> linesInMemory = new ArrayList<>();
private final List<String> peekedLines = new LinkedList<>();
/**
* Initializes an AbstractLogReader instance.
*
* @param entryParsers The supplier of a set of entry parsers
* @throws java.lang.NullPointerException If entryParsers.get() or readIterator() returns null.
*/
protected AbstractLogReader(final EntryParsers entryParsers) {
this.entryParsers = Objects.requireNonNull(entryParsers.get(), "entryParsers.get()");
this.readIterator = Objects.requireNonNull(readIterator(), "readIterator()");
}
@Override
public LogEntry readNextEntry() throws NotReadableException {
List<Exception> occurredExceptions = new ArrayList<>();
String line = readLineFromLogAndSave();
for (EntryParser entryParser : entryParsers) {
if (!entryParser.isParsable(line)) {
continue;
}
try {
LogEntry result = entryParser.parse(line, new LineReader() {
@Override
public String readNextLine() {
return readLineFromLogAndSave();
}
@Override
public boolean hasNextLine() {
return hasNextEntry();
}
@Override
public boolean nextLineMatches(final Predicate<String> condition) {
String line = readLineFromPeekedLinesOrLog();
Objects.requireNonNull(line, "line");
peekedLines.add(line);
return condition.test(line);
}
});
linesInMemory.clear();
return result;
} catch (NotParsableException | NoSuchElementException ex) {
occurredExceptions.add(ex);
//try next entry parser
}
}
List<String> notParsableLines = new ArrayList<>(linesInMemory);
linesInMemory.clear();
throw new NotReadableException(notParsableLines, occurredExceptions);
}
@Override
public boolean hasNextEntry() {
return (!peekedLines.isEmpty() || readIterator.hasNext());
}
/**
* Returns an iterator used to read from the log source.
*
* @return The iterator used to read from the log source.
*/
protected abstract Iterator<String> readIterator();
/**
* Returns the next line from the lines that have been peeked, or if empty, from the log source.
*
* @return The next line from the lines that have been peeked, or if empty, from the log source.
* @throws java.util.NoSuchElementException If no more lines are present.
*/
private String readLineFromPeekedLinesOrLog() {
if (!peekedLines.isEmpty()) {
return peekedLines.remove(0);
}
return readIterator.next();
}
/**
* Returns the next line from the log source and saves it.
*
* @return The next line from the log source.
* @throws java.util.NoSuchElementException If no more lines are present.
* @throws java.lang.NullPointerException If line is null.
*/
private String readLineFromLogAndSave() {
String line = readLineFromPeekedLinesOrLog();
Objects.requireNonNull(line, "line");
linesInMemory.add(line);
return line;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment