From 5b8c57f577151d8de4bd4ef95d9568ec3ba99fc9 Mon Sep 17 00:00:00 2001 From: bculkin2442 Date: Mon, 27 Mar 2017 23:25:47 -0400 Subject: Implement more BlockReader types Adds additional useful block reader types. * LayeredBlockReader, which represents priority * SerialBlockReader, which concatenates readers --- .../main/java/bjc/utils/ioutils/BlockReaders.java | 40 +++++++-- .../java/bjc/utils/ioutils/LayeredBlockReader.java | 70 ++++++++++++++++ .../java/bjc/utils/ioutils/SerialBlockReader.java | 98 ++++++++++++++++++++++ .../java/bjc/utils/ioutils/SimpleBlockReader.java | 2 + 4 files changed, 204 insertions(+), 6 deletions(-) create mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/LayeredBlockReader.java create mode 100644 BJC-Utils2/src/main/java/bjc/utils/ioutils/SerialBlockReader.java (limited to 'BJC-Utils2/src/main/java/bjc/utils') diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/BlockReaders.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/BlockReaders.java index 8a359b8..3d71f52 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/BlockReaders.java +++ b/BJC-Utils2/src/main/java/bjc/utils/ioutils/BlockReaders.java @@ -13,10 +13,10 @@ public class BlockReaders { * Create a new simple block reader that works off a regex. * * @param blockDelim - * The regex that seperates blocks. + * The regex that separates blocks. * * @param source - * The reader to get blocks from. + * The reader to get blocks from. * * @return A configured simple reader. */ @@ -28,7 +28,7 @@ public class BlockReaders { * Create a new pushback block reader. * * @param src - * The block reader to read blocks from. + * The block reader to read blocks from. * * @return A configured pushback reader. */ @@ -40,14 +40,42 @@ public class BlockReaders { * Create a new triggered block reader. * * @param source - * The block reader to read blocks from. + * The block reader to read blocks from. * * @param action - * The action to execute before reading a block. + * The action to execute before reading a block. * * @return A configured triggered block reader. */ public static BlockReader trigger(BlockReader source, Runnable action) { return new TriggeredBlockReader(source, action); } -} + + /** + * Create a new layered block reader. + * + * @param primary + * The first source to read blocks from. + * + * @param secondary + * The second source to read blocks from. + * + * @return A configured layered block reader. + */ + public static BlockReader layered(BlockReader primary, BlockReader secondary) { + return new LayeredBlockReader(primary, secondary); + } + + /** + * Create a new serial block reader. + * + * @param readers + * The readers to pull from, in the order to pull from + * them. + * + * @return A configured serial block reader. + */ + public static BlockReader serial(BlockReader... readers) { + return new SerialBlockReader(readers); + } +} \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/LayeredBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/LayeredBlockReader.java new file mode 100644 index 0000000..ed7a1b9 --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/ioutils/LayeredBlockReader.java @@ -0,0 +1,70 @@ +package bjc.utils.ioutils; + +import java.io.IOException; + +/** + * A block reader that supports draining all the blocks from one reading before + * swapping to another. + * + * This is more a 'prioritize blocks from one over the other', than a 'read all + * the blocks from one, then all the blocks from the other'. If you need that, + * look at {@link SerialBlockReader}. + * + * @author bjculkin + * + */ +public class LayeredBlockReader implements BlockReader { + private BlockReader first; + private BlockReader second; + + private int blockNo; + + /** + * Create a new layered block reader. + * + * @param primary + * The first source to read blocks from. + * + * @param secondary + * The second source to read blocks from. + */ + public LayeredBlockReader(BlockReader primary, BlockReader secondary) { + first = primary; + second = secondary; + } + + @Override + public boolean hasNextBlock() { + return first.hasNextBlock() || second.hasNextBlock(); + } + + @Override + public Block getBlock() { + Block firstBlock = first.getBlock(); + + return firstBlock == null ? second.getBlock() : firstBlock; + } + + @Override + public boolean nextBlock() { + boolean gotFirst = first.nextBlock(); + + boolean succ = gotFirst ? gotFirst : second.nextBlock(); + + if (succ) blockNo += 1; + + return succ; + } + + @Override + public int getBlockCount() { + return blockNo; + } + + @Override + public void close() throws IOException { + second.close(); + + first.close(); + } +} \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/SerialBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/SerialBlockReader.java new file mode 100644 index 0000000..0ae969d --- /dev/null +++ b/BJC-Utils2/src/main/java/bjc/utils/ioutils/SerialBlockReader.java @@ -0,0 +1,98 @@ +package bjc.utils.ioutils; + +import java.io.IOException; +import java.util.Deque; + +/** + * Provides a means of concatenating two block readers. + * + * @author bjculkin + * + */ +public class SerialBlockReader implements BlockReader { + private Deque readerQueue; + + private int blockNo; + + /** + * Create a new serial block reader. + * + * @param readers + * The readers to pull from, in the order to pull from + * them. + */ + public SerialBlockReader(BlockReader... readers) { + for (BlockReader reader : readers) { + readerQueue.add(reader); + } + } + + @Override + public boolean hasNextBlock() { + if (readerQueue.isEmpty()) return false; + + boolean hasBlock = readerQueue.peek().hasNextBlock(); + + boolean cont = hasBlock || readerQueue.isEmpty(); + + while (!cont) { + try { + readerQueue.pop().close(); + } catch (IOException ioex) { + throw new IllegalStateException("Exception thrown by discarded reader", ioex); + } + + hasBlock = readerQueue.peek().hasNextBlock(); + + cont = hasBlock || readerQueue.isEmpty(); + } + + return hasBlock; + } + + @Override + public Block getBlock() { + if (readerQueue.isEmpty()) + return null; + else return readerQueue.peek().getBlock(); + } + + @Override + public boolean nextBlock() { + if (readerQueue.isEmpty()) return false; + + boolean gotBlock = readerQueue.peek().nextBlock(); + + boolean cont = gotBlock || readerQueue.isEmpty(); + + while (!cont) { + try { + readerQueue.pop().close(); + } catch (IOException ioex) { + throw new IllegalStateException("Exception thrown by discarded reader", ioex); + } + + gotBlock = readerQueue.peek().nextBlock(); + + cont = gotBlock || readerQueue.isEmpty(); + } + + if (cont) blockNo += 1; + + return cont; + } + + @Override + public int getBlockCount() { + return blockNo; + } + + @Override + public void close() throws IOException { + while (!readerQueue.isEmpty()) { + BlockReader reader = readerQueue.pop(); + + reader.close(); + } + } +} \ No newline at end of file diff --git a/BJC-Utils2/src/main/java/bjc/utils/ioutils/SimpleBlockReader.java b/BJC-Utils2/src/main/java/bjc/utils/ioutils/SimpleBlockReader.java index 329effc..6b868bb 100644 --- a/BJC-Utils2/src/main/java/bjc/utils/ioutils/SimpleBlockReader.java +++ b/BJC-Utils2/src/main/java/bjc/utils/ioutils/SimpleBlockReader.java @@ -72,6 +72,8 @@ public class SimpleBlockReader implements BlockReader { return true; } catch (NoSuchElementException nseex) { + currBlock = null; + return false; } } -- cgit v1.2.3