package com.activequant.utils; import java.util.Date; import com.activequant.domainmodel.TimeStamp; /** * Utility class to generate unique date for market events. * The problem is that some feed sources do not supply milliseconds (Opentick's) * in the date field. Since AQ code depends on date to be unique within the * type and feed source, we need to fake millisecond part. * This object generates unique date by catching duplicates and * assigning milliseconds sequentially. * <br> * Optionally, it is possible to generate a timestamp from a number like * the number of milliseconds since unix epoch start. * <br> * <b>History:</b><br> * - [27.11.2007] Created (Mike Kroutikov)<br> * - [26.09.2009] Adding generate(long) method (Ulrich Staudinger)<br> * * @author Mike Kroutikov * @author Ulrich Staudinger */ public class UniqueTimeStampGenerator { private static long AMBIGUATION_UNITS_IN_MILLIS = 1000000; private long lastMillis = 0L; private long nanos = 0; private static UniqueTimeStampGenerator instance = null; public TimeStamp now(){ return generate(new Date()); } public TimeStamp generate(Date input) { long time = input.getTime(); return generate(time); } public TimeStamp generate(long inputInMilliseconds) { if(inputInMilliseconds > lastMillis) { lastMillis = inputInMilliseconds; nanos = 0; } else if(inputInMilliseconds == lastMillis) { nanos++; if(nanos >= AMBIGUATION_UNITS_IN_MILLIS) { // can come here only if events are generated at rate one per nanosecond // practically impossible throw new AssertionError("failed to disambiguate"); } } else { throw new AssertionError("input dates are out-of-order : "+inputInMilliseconds+" is lower than "+lastMillis); } return new TimeStamp(lastMillis * AMBIGUATION_UNITS_IN_MILLIS + nanos); // disambiguate } public static UniqueTimeStampGenerator getInstance(){ if(instance==null) instance = new UniqueTimeStampGenerator(); return instance; } }