package com.ldbc.driver.generator;
import com.google.common.collect.Ordering;
import com.ldbc.driver.csv.charseeker.CharSeeker;
import com.ldbc.driver.csv.charseeker.Extractors;
import com.ldbc.driver.csv.charseeker.Mark;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import static java.lang.String.format;
public class CsvEventStreamReaderTimedTypedCharSeeker<BASE_EVENT_TYPE> implements Iterator<BASE_EVENT_TYPE>
{
private final EventDecoder<BASE_EVENT_TYPE>[] decoders;
private final CharSeeker charSeeker;
private final Extractors extractors;
private final Mark mark;
private final int[] columnDelimiters;
private BASE_EVENT_TYPE nextEvent = null;
public CsvEventStreamReaderTimedTypedCharSeeker( CharSeeker charSeeker,
Extractors extractors,
Map<Integer,EventDecoder<BASE_EVENT_TYPE>> decoders,
int columnDelimiter )
{
this.charSeeker = charSeeker;
this.extractors = extractors;
this.mark = new Mark();
this.columnDelimiters = new int[]{columnDelimiter};
int minEventTypeCode = Ordering.<Integer>natural().min( decoders.keySet() );
int maxEventTypeCode = Ordering.<Integer>natural().max( decoders.keySet() );
if ( minEventTypeCode < 0 )
{
throw new GeneratorException( "Event codes must be positive numbers: " + decoders.keySet().toString() );
}
this.decoders = new EventDecoder[maxEventTypeCode + 1];
for ( Integer eventTypeCode : decoders.keySet() )
{
this.decoders[eventTypeCode] = decoders.get( eventTypeCode );
}
}
@Override
public boolean hasNext()
{
if ( null == nextEvent )
{
nextEvent = getNextEvent();
}
return null != nextEvent;
}
@Override
public BASE_EVENT_TYPE next()
{
if ( null == nextEvent )
{
nextEvent = getNextEvent();
}
BASE_EVENT_TYPE result = nextEvent;
nextEvent = null;
return result;
}
BASE_EVENT_TYPE getNextEvent()
{
try
{
long scheduledStartTime;
if ( charSeeker.seek( mark, columnDelimiters ) )
{
scheduledStartTime = charSeeker.extract( mark, extractors.long_() ).longValue();
}
else
{
// if first column of next row contains nothing it means the file is finished
return null;
}
long dependencyTime;
if ( charSeeker.seek( mark, columnDelimiters ) )
{
dependencyTime = charSeeker.extract( mark, extractors.long_() ).longValue();
}
else
{
throw new GeneratorException( "No dependency time found" );
}
int eventType;
if ( charSeeker.seek( mark, columnDelimiters ) )
{
eventType = charSeeker.extract( mark, extractors.int_() ).intValue();
}
else
{
throw new GeneratorException( "No event type found" );
}
EventDecoder<BASE_EVENT_TYPE> decoder = decoders[eventType];
if ( null == decoder )
{
throw new NoSuchElementException(
format( "No decoder found that matches this column\nDECODER KEY: %s", eventType )
);
}
return decoder
.decodeEvent( scheduledStartTime, dependencyTime, charSeeker, extractors, columnDelimiters, mark );
}
catch ( IOException e )
{
throw new GeneratorException( "Error while retrieving next event", e );
}
}
@Override
public void remove()
{
throw new UnsupportedOperationException( format( "%s does not support remove()", getClass().getSimpleName() ) );
}
public static interface EventDecoder<BASE_EVENT_TYPE>
{
BASE_EVENT_TYPE decodeEvent( long scheduledStartTime, long dependencyTime, CharSeeker charSeeker,
Extractors extractors, int[] columnDelimiters, Mark mark );
}
}