package com.ldbc.driver.generator;
import com.ldbc.driver.Operation;
import com.ldbc.driver.util.Function1;
import java.util.Iterator;
public class TimeMappingOperationGenerator extends Generator<Operation>
{
private final Iterator<Operation> operations;
private final long newStartTimeAsMilli;
private final Double timeCompressionRatio;
private Function1<Long,Long,RuntimeException> timeOffsetAsMilliFun = null;
private Function1<Long,Long,RuntimeException> startTimeAsMilliCompressionFun = null;
TimeMappingOperationGenerator(
Iterator<Operation> operations,
long newStartTimeAsMilli,
Double timeCompressionRatio )
{
this.operations = operations;
this.newStartTimeAsMilli = newStartTimeAsMilli;
this.timeCompressionRatio = timeCompressionRatio;
}
@Override
protected Operation doNext() throws GeneratorException
{
if ( false == operations.hasNext() )
{ return null; }
Operation nextOperation = operations.next();
if ( null == timeOffsetAsMilliFun )
{
// Create time offset function
long firstStartTimeAsMilli = nextOperation.scheduledStartTimeAsMilli();
if ( newStartTimeAsMilli > firstStartTimeAsMilli )
{
// offset to future
long offsetAsMilli = newStartTimeAsMilli - firstStartTimeAsMilli;
timeOffsetAsMilliFun = new TimeFutureOffsetFun( offsetAsMilli );
}
else
{
// offset to past
long offsetAsMilli = firstStartTimeAsMilli - newStartTimeAsMilli;
timeOffsetAsMilliFun = new TimePastOffsetFun( offsetAsMilli );
}
// Create time compression function
if ( null == timeCompressionRatio )
{
startTimeAsMilliCompressionFun = new IdentityTimeFun();
}
else
{
startTimeAsMilliCompressionFun = new TimeCompressionFun(
timeCompressionRatio,
timeOffsetAsMilliFun.apply( nextOperation.scheduledStartTimeAsMilli() )
);
}
}
long offsetStartTimeAsMilli = timeOffsetAsMilliFun.apply( nextOperation.scheduledStartTimeAsMilli() );
long offsetAndCompressedStartTimeAsMilli = startTimeAsMilliCompressionFun.apply( offsetStartTimeAsMilli );
nextOperation.setScheduledStartTimeAsMilli( offsetAndCompressedStartTimeAsMilli );
return nextOperation;
}
private class IdentityTimeFun implements Function1<Long,Long,RuntimeException>
{
@Override
public Long apply( Long timeAsMilli )
{
return timeAsMilli;
}
}
private class TimeFutureOffsetFun implements Function1<Long,Long,RuntimeException>
{
private final long offsetAsMilli;
private TimeFutureOffsetFun( long offsetAsMilli )
{
this.offsetAsMilli = offsetAsMilli;
}
@Override
public Long apply( Long timeAsMilli )
{
return timeAsMilli + offsetAsMilli;
}
}
private class TimePastOffsetFun implements Function1<Long,Long,RuntimeException>
{
private final long offsetAsMilli;
private TimePastOffsetFun( long offsetAsMilli )
{
this.offsetAsMilli = offsetAsMilli;
}
@Override
public Long apply( Long timeAsMilli )
{
return timeAsMilli - offsetAsMilli;
}
}
private class TimeCompressionFun implements Function1<Long,Long,RuntimeException>
{
private final double timeCompressionRatio;
private long firstTimeAsMilli;
private TimeCompressionFun( double timeCompressionRatio, long firstTimeAsMilli )
{
this.timeCompressionRatio = timeCompressionRatio;
this.firstTimeAsMilli = firstTimeAsMilli;
}
@Override
public Long apply( Long timeAsMilli )
{
long durationFromOriginalStartTimeAsMilli = timeAsMilli - firstTimeAsMilli;
long compressedDurationFromOriginalStartTimeAsMilli =
Math.round( durationFromOriginalStartTimeAsMilli * timeCompressionRatio );
return firstTimeAsMilli + compressedDurationFromOriginalStartTimeAsMilli;
}
}
}