package com.limegroup.gnutella.dime;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
/**
* Parser for creating DIMERecords from input.
*
* See: http://www.gotdotnet.com/team/xml_wsspecs/dime/dime.htm
* (or http://www.perfectxml.com/DIME.asp )
* for information about DIME.
*/
public class DIMEParser implements Iterator {
/**
* The input stream this parser is working off of.
*/
private final InputStream IN;
/**
* Whether or not we've read the last record.
*/
private boolean _lastRead = false;
/**
* Whether or not we've read the first record.
*/
private boolean _firstRead = false;
/**
* Constructs a new DIMEParser.
*/
public DIMEParser(InputStream in) {
IN = in;
}
/**
* Returns the next element.
*/
public Object next() {
try {
return nextRecord();
} catch(IOException ioe) {
throw new NoSuchElementException(ioe.getMessage());
}
}
/**
* Returns the next record we can parse.
*/
public DIMERecord nextRecord() throws IOException {
return getNext();
}
/**
* Return a list of all possible records we can still read from the stream.
*
* If all records are already read, returns an empty list.
*/
public List getRecords() throws IOException {
if(_lastRead)
return Collections.EMPTY_LIST;
List records = new LinkedList();
while(!_lastRead)
records.add(getNext());
return records;
}
/**
* Determines if this has more records to read.
*/
public boolean hasNext() {
return !_lastRead;
}
/**
* Unsupported operation.
*/
public void remove() {
throw new UnsupportedOperationException();
}
/**
* Reads the next record from the stream, updating the internal variables.
* If the read record is the first and doesn't have the ME flag set,
* throws IOException.
* If this is called when _lastRead is already set, throws IOException.
*/
private DIMERecord getNext() throws IOException {
if(_lastRead)
throw new IOException("already read last message.");
DIMERecord next = DIMERecord.createFromStream(IN);
if(next.isLastRecord())
_lastRead = true;
if(!_firstRead && !next.isFirstRecord())
throw new IOException("middle of stream.");
else if(_firstRead && next.isFirstRecord())
throw new IOException("two first records.");
_firstRead = true;
return next;
}
}