001package org.javasimon.callback.timeline; 002 003import org.javasimon.callback.lastsplits.CircularList; 004 005/** 006 * Collection of values sorted on a time line. 007 * 008 * @author gerald 009 */ 010public abstract class Timeline<TR extends TimeRange> { 011 012 /** List of time ranges. */ 013 protected final CircularList<TR> timeRanges; 014 /** Time range width in milliseconds. */ 015 protected final long timeRangeWidth; 016 017 /** Last used time range. */ 018 private TR lastTimeRange; 019 020 /** 021 * Main constructor. 022 * 023 * @param capacity Number of time ranges 024 * @param timeRangeWidth Width of each time range 025 */ 026 protected Timeline(int capacity, long timeRangeWidth) { 027 this.timeRanges = new CircularList<>(capacity); 028 this.timeRangeWidth = timeRangeWidth; 029 } 030 031 /** 032 * Creates time range (factory method). 033 * 034 * @param startTimestamp Time range start 035 * @param endTimestamp Time range end 036 * @return created time range 037 */ 038 protected abstract TR createTimeRange(long startTimestamp, long endTimestamp); 039 040 /** 041 * Returns existing time range if it already exists or create a new one. 042 */ 043 protected final TR getOrCreateTimeRange(long timestamp) { 044 TR timeRange; 045 if (lastTimeRange == null || timestamp > lastTimeRange.getEndTimestamp()) { 046 // New time range 047 long roundedTimestamp = timestamp - timestamp % timeRangeWidth; 048 timeRange = createTimeRange(roundedTimestamp, roundedTimestamp + timeRangeWidth); 049 timeRanges.add(timeRange); 050 lastTimeRange = timeRange; 051 } else if (timestamp >= lastTimeRange.getStartTimestamp()) { 052 // Current time range 053 timeRange = lastTimeRange; 054 } else { 055 // Old time range 056 timeRange = null; 057 // Not very good from performance point of view 058 // iterating from end till start would be a better solution 059 for (TR oldTimeRange : timeRanges) { 060 if (oldTimeRange.containsTimestamp(timestamp)) { 061 timeRange = oldTimeRange; 062 break; 063 } 064 } 065 } 066 067 return timeRange; 068 } 069 070 public abstract TimelineSample<TR> sample(); 071}