package org.limewire.bittorrent.bencoding; import java.io.IOException; import java.nio.channels.ReadableByteChannel; /** * A Bencode element (http://en.wikipedia.org/wiki/Bencoding) that can be * used for Lists and Maps. This works for reading Maps because they're read * as a list of key/value pairs. */ public abstract class BEAbstractCollection<T> extends Token<T> { /** Whether the token has been parsed completely */ protected boolean done; /** The current element being parsed. */ private Token<?> currentElement; public BEAbstractCollection(ReadableByteChannel chan) { super(chan); result = createCollection(); } /** Creates the underlying collection to store the result. */ protected abstract T createCollection(); /** Adds a newly parsed item into the underlying collection. */ protected abstract void add(Object o); /** Parses an item from the stream. */ protected abstract Token<?> getNewElement() throws IOException; /** Determines if all parsing is finished for this token. */ @Override protected boolean isDone() { return done; } /** Reads a single item from the stream. */ @Override public void handleRead() throws IOException { if (isDone()) throw new IllegalStateException("token is done, don't read to it"); while(true) { if (currentElement == null) currentElement = getNewElement(); if (currentElement == null) return; if (currentElement.getResult() == Token.TERMINATOR) { done = true; return; } currentElement.handleRead(); Object result = currentElement.getResult(); if (result == null) return; if (result == Token.TERMINATOR) { done = true; return; } add(result); currentElement = null; } } }