@Test void testLowerBound() { GapAwareTrackingToken token1 = GapAwareTrackingToken.newInstance(3L, singleton(1L)); GapAwareTrackingToken token2 = GapAwareTrackingToken.newInstance(4L, singleton(2L)); GapAwareTrackingToken token3 = GapAwareTrackingToken.newInstance(2L, asList(0L, 1L)); GapAwareTrackingToken token4 = GapAwareTrackingToken.newInstance(3L, emptySortedSet()); GapAwareTrackingToken token5 = GapAwareTrackingToken.newInstance(3L, singleton(2L)); GapAwareTrackingToken token6 = GapAwareTrackingToken.newInstance(1L, emptySortedSet()); assertEquals(token1.lowerBound(token2), GapAwareTrackingToken.newInstance(3L, asList(1L, 2L))); assertEquals(token1.lowerBound(token3), token3); assertEquals(token1.lowerBound(token4), token1); assertEquals(token1.lowerBound(token5), GapAwareTrackingToken.newInstance(3L, asList(1L, 2L))); assertEquals(token1.lowerBound(token6), GapAwareTrackingToken.newInstance(0L, emptySortedSet())); assertEquals(token2.lowerBound(token3), GapAwareTrackingToken.newInstance(-1L, emptySortedSet())); }
@Override public GapAwareTrackingToken lowerBound(TrackingToken other) { Assert.isTrue(other instanceof GapAwareTrackingToken, () -> "Incompatible token type provided."); GapAwareTrackingToken otherToken = (GapAwareTrackingToken) other; SortedSet<Long> mergedGaps = new ConcurrentSkipListSet<>(this.gaps); mergedGaps.addAll(otherToken.gaps); long mergedIndex = calculateIndex(otherToken, mergedGaps); mergedGaps.removeIf(i -> i >= mergedIndex); return new GapAwareTrackingToken(mergedIndex, mergedGaps, Math.min(gapTruncationIndex, otherToken.gapTruncationIndex)); }
GapAwareTrackingToken implements TrackingToken, Serializable { @Override public GapAwareTrackingToken lowerBound(TrackingToken other) { Assert.isTrue(other instanceof GapAwareTrackingToken, () -> "Incompatible token type provided."); GapAwareTrackingToken otherToken = (GapAwareTrackingToken) other; SortedSet<Long> mergedGaps = new ConcurrentSkipListSet<>(this.gaps); mergedGaps.addAll(otherToken.gaps); long mergedIndex = calculateIndex(otherToken, mergedGaps); mergedGaps.removeIf(i -> i >= mergedIndex); return new GapAwareTrackingToken(mergedIndex, mergedGaps, Math.min(gapTruncationIndex, otherToken.gapTruncationIndex)); } }
GapAwareTrackingToken implements TrackingToken, Serializable { @Override public GapAwareTrackingToken lowerBound(TrackingToken other) { Assert.isTrue(other instanceof GapAwareTrackingToken, () -> "Incompatible token type provided."); GapAwareTrackingToken otherToken = (GapAwareTrackingToken) other; SortedSet<Long> mergedGaps = new ConcurrentSkipListSet<>(this.gaps); mergedGaps.addAll(otherToken.gaps); long mergedIndex = calculateIndex(otherToken, mergedGaps); mergedGaps.removeIf(i -> i >= mergedIndex); return new GapAwareTrackingToken(mergedIndex, mergedGaps, Math.min(gapTruncationIndex, otherToken.gapTruncationIndex)); } @JsonCreator @ConstructorProperties({"index", "gaps"})  GapAwareTrackingToken(@JsonProperty("index") long index, @JsonProperty("gaps") Collection<Long> gaps); private  GapAwareTrackingToken(long index, SortedSet<Long> gaps, long gapTruncationIndex); }
GapAwareTrackingToken implements TrackingToken, Serializable { @Override public GapAwareTrackingToken lowerBound(TrackingToken other) { Assert.isTrue(other instanceof GapAwareTrackingToken, () -> "Incompatible token type provided."); GapAwareTrackingToken otherToken = (GapAwareTrackingToken) other; SortedSet<Long> mergedGaps = new ConcurrentSkipListSet<>(this.gaps); mergedGaps.addAll(otherToken.gaps); long mergedIndex = calculateIndex(otherToken, mergedGaps); mergedGaps.removeIf(i -> i >= mergedIndex); return new GapAwareTrackingToken(mergedIndex, mergedGaps, Math.min(gapTruncationIndex, otherToken.gapTruncationIndex)); } @JsonCreator @ConstructorProperties({"index", "gaps"})  GapAwareTrackingToken(@JsonProperty("index") long index, @JsonProperty("gaps") Collection<Long> gaps); private  GapAwareTrackingToken(long index, SortedSet<Long> gaps, long gapTruncationIndex); static GapAwareTrackingToken newInstance(long index, Collection<Long> gaps); GapAwareTrackingToken advanceTo(long index, int maxGapOffset); GapAwareTrackingToken withGapsTruncatedAt(long truncationPoint); long getIndex(); SortedSet<Long> getGaps(); @Override GapAwareTrackingToken lowerBound(TrackingToken other); @Override TrackingToken upperBound(TrackingToken otherToken); @Override boolean covers(TrackingToken other); boolean hasGaps(); @Override boolean equals(Object o); @Override int hashCode(); @Override String toString(); @Override OptionalLong position(); }
GapAwareTrackingToken implements TrackingToken, Serializable { @Override public GapAwareTrackingToken lowerBound(TrackingToken other) { Assert.isTrue(other instanceof GapAwareTrackingToken, () -> "Incompatible token type provided."); GapAwareTrackingToken otherToken = (GapAwareTrackingToken) other; SortedSet<Long> mergedGaps = new ConcurrentSkipListSet<>(this.gaps); mergedGaps.addAll(otherToken.gaps); long mergedIndex = calculateIndex(otherToken, mergedGaps); mergedGaps.removeIf(i -> i >= mergedIndex); return new GapAwareTrackingToken(mergedIndex, mergedGaps, Math.min(gapTruncationIndex, otherToken.gapTruncationIndex)); } @JsonCreator @ConstructorProperties({"index", "gaps"})  GapAwareTrackingToken(@JsonProperty("index") long index, @JsonProperty("gaps") Collection<Long> gaps); private  GapAwareTrackingToken(long index, SortedSet<Long> gaps, long gapTruncationIndex); static GapAwareTrackingToken newInstance(long index, Collection<Long> gaps); GapAwareTrackingToken advanceTo(long index, int maxGapOffset); GapAwareTrackingToken withGapsTruncatedAt(long truncationPoint); long getIndex(); SortedSet<Long> getGaps(); @Override GapAwareTrackingToken lowerBound(TrackingToken other); @Override TrackingToken upperBound(TrackingToken otherToken); @Override boolean covers(TrackingToken other); boolean hasGaps(); @Override boolean equals(Object o); @Override int hashCode(); @Override String toString(); @Override OptionalLong position();  }