diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/TimeRange.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/TimeRange.java index b0742aee940..32963d650f8 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/TimeRange.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/TimeRange.java @@ -2,13 +2,9 @@ package com.sap.sailing.domain.common; import java.io.Serializable; -/** - * A TimeRange defined by a starting timepoint {@link #from()}, and an ending timepoint {@link #to()}, which are both inclusive. - * @author Fredrik Teschke - * - */ public interface TimeRange extends Comparable, Serializable { TimePoint from(); + TimePoint to(); /** @@ -35,6 +31,16 @@ public interface TimeRange extends Comparable, Serializable { boolean endsAfter(TimeRange other); + /** + * Is the time range open ended towards older timepoints? + */ + boolean openBeginning(); + + /** + * Is the time range open ended towards newer timepoints? + */ + boolean openEnd(); + /** * Get time-difference between the timepoint and this timerange. * It will be 0 if the timepoint lies within the timerange, otherwise the time-difference @@ -43,4 +49,14 @@ public interface TimeRange extends Comparable, Serializable { * @return */ long timeDifference(TimePoint timePoint); + + /** + * Merges the two ranges, only possible if {@code other} {@link #intersects()} this range. + */ + TimeRange union(TimeRange other); + + /** + * Intersection of the two ranges, only possible if {@code other} {@link #intersects()} this range. + */ + TimeRange intersection(TimeRange other); } \ No newline at end of file diff --git a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/TimeRangeImpl.java b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/TimeRangeImpl.java index 2ba42db158e..1b821c630ad 100644 --- a/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/TimeRangeImpl.java +++ b/java/com.sap.sailing.domain.common/src/com/sap/sailing/domain/common/impl/TimeRangeImpl.java @@ -5,17 +5,19 @@ import com.sap.sailing.domain.common.TimeRange; import com.sap.sailing.domain.common.impl.Util.Pair; public class TimeRangeImpl extends Pair implements TimeRange { + public static final TimePoint BeginningOfTime = new MillisecondsTimePoint(Long.MIN_VALUE); + public static final TimePoint EndOfTime = new MillisecondsTimePoint(Long.MAX_VALUE); private static final long serialVersionUID = 8710198176227507300L; public TimeRangeImpl(TimePoint from, TimePoint to) { - super(from, to); - if (from.after(to)) throw new IllegalArgumentException(String.format("from (%s) must lie before to (%s) in a TimeRange", from, to)); + super(from == null ? BeginningOfTime : from, to == null ? EndOfTime : to); + if (from().after(to())) throw new IllegalArgumentException(String.format("from (%s) must lie before to (%s) in a TimeRange", from(), to())); } @Override - public int compareTo(TimeRange arg0) { - // TODO Auto-generated method stub - return 0; + public int compareTo(TimeRange other) { + if (other.from() == from() && other.to() == to()) return 0; + return startsBefore(other) ? -1 : 1; } @Override @@ -30,7 +32,7 @@ public class TimeRangeImpl extends Pair implements TimeRan @Override public boolean liesWithin(TimeRange other) { - return from().compareTo(other.from()) >= 0 && to().compareTo(other.to()) <=0; + return from().compareTo(other.from()) >= 0 && to().compareTo(other.to()) <= 0; } @Override @@ -64,4 +66,30 @@ public class TimeRangeImpl extends Pair implements TimeRan if (timePoint.before(from())) return from().asMillis() - timePoint.asMillis(); return to().asMillis() - timePoint.asMillis(); } + + @Override + public TimeRange union(TimeRange other) { + if (! intersects(other)) return null; + TimePoint newFrom = startsBefore(other) ? from() : other.from(); + TimePoint newTo = endsAfter(other) ? to() : other.to(); + return new TimeRangeImpl(newFrom, newTo); + } + + @Override + public boolean openBeginning() { + return from().equals(BeginningOfTime); + } + + @Override + public boolean openEnd() { + return to().equals(EndOfTime); + } + + @Override + public TimeRange intersection(TimeRange other) { + if (! intersects(other)) return null; + TimePoint newFrom = startsBefore(other) ? other.from() : from(); + TimePoint newTo = endsAfter(other) ? other.to() : to(); + return new TimeRangeImpl(newFrom, newTo); + } } diff --git a/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/MappingAnalyzerTest.java b/java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/DeviceMappingFinderTest.java similarity index 100% rename from java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/MappingAnalyzerTest.java rename to java/com.sap.sailing.domain.shared.android.test/src/com/sap/sailing/domain/racelog/tracking/analyzing/test/DeviceMappingFinderTest.java diff --git a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/TimeRangeTest.java b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/TimeRangeTest.java index cd7557cf28a..1baa6fc50bd 100644 --- a/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/TimeRangeTest.java +++ b/java/com.sap.sailing.domain.test/src/com/sap/sailing/domain/common/test/TimeRangeTest.java @@ -1,5 +1,9 @@ package com.sap.sailing.domain.common.test; +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.assertNull; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import junit.framework.Assert; import org.junit.Test; @@ -54,4 +58,62 @@ public class TimeRangeTest { Assert.assertTrue(one.intersects(two)); Assert.assertTrue(two.intersects(one)); } + + @Test + public void openRanges() { + TimeRange one = new TimeRangeImpl(new MillisecondsTimePoint(0), null); + TimeRange two = create(5, 10); + TimeRange three = new TimeRangeImpl(null, new MillisecondsTimePoint(15)); + + assertTrue(two.liesWithin(one)); + assertTrue(two.liesWithin(three)); + assertTrue(one.intersects(three)); + assertTrue(one.endsAfter(three)); + assertFalse(one.startsBefore(three)); + } + + @Test + public void union() { + TimeRange one = create(5, 10); + TimeRange two = create(7, 12); + + TimeRange union = one.union(two); + assertEquals(5, union.from().asMillis()); + assertEquals(12, union.to().asMillis()); + + two = create(11, 16); + assertNull(one.union(two)); + + two = create(7, Long.MAX_VALUE); + union = two.union(one); + TimeRange union2 = one.union(two); + assertEquals(5, union.from().asMillis()); + assertEquals(5, union2.from().asMillis()); + assertEquals(Long.MAX_VALUE, union.to().asMillis()); + assertEquals(Long.MAX_VALUE, union2.to().asMillis()); + } + + @Test + public void intersection() { + TimeRange one = create(5, 10); + TimeRange two = create(7, 12); + + TimeRange intersection = one.intersection(two); + assertEquals(7, intersection.from().asMillis()); + assertEquals(10, intersection.to().asMillis()); + + two = create(11, 16); + assertNull(one.intersection(two)); + + two = create(7, Long.MAX_VALUE); + intersection = two.intersection(one); + assertEquals(7, intersection.from().asMillis()); + assertEquals(10, intersection.to().asMillis()); + + one = create(0, Long.MAX_VALUE); + two = create(Long.MIN_VALUE, 10); + intersection = two.intersection(one); + assertEquals(0, intersection.from().asMillis()); + assertEquals(10, intersection.to().asMillis()); + } }