Created
January 16, 2015 18:50
-
-
Save skiwi2/d6e68f8dee55c2288244 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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