tmf.core: simplify timestamp implementations
authorMatthew Khouzam <matthew.khouzam@ericsson.com>
Fri, 8 Apr 2016 14:25:19 +0000 (10:25 -0400)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Fri, 22 Apr 2016 20:48:18 +0000 (16:48 -0400)
This patch makes BIG_BANG and BIG_CRUNCH and ZERO special singleton
objects. They now normalize to themselves. Big bang and big crunch are
always the largest or smallest values.

It also internalizes TmfRealTimestamp inside TmfTimestamp as
TmfTimestamp$Impl.

The timestamp comparison is very streamlined. The performance
should be similar though.

One bug found that will never occur in the real world:
additions with -Long.MIN_VALUE gave errors as -Long.MIN_VALUE ==
LONG.MIN_VALUE.

Change-Id: I284ed1b8f0dd1f6d5299e172dd07128d53ac5945
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/70245
Reviewed-by: Hudson CI
Reviewed-by: Patrick Tasse <patrick.tasse@gmail.com>
Tested-by: Patrick Tasse <patrick.tasse@gmail.com>
tmf/org.eclipse.tracecompass.tmf.core.tests/src/org/eclipse/tracecompass/tmf/core/tests/event/TmfNanoTimestampTest.java
tmf/org.eclipse.tracecompass.tmf.core.tests/src/org/eclipse/tracecompass/tmf/core/tests/event/TmfSecondTimestampTest.java
tmf/org.eclipse.tracecompass.tmf.core.tests/src/org/eclipse/tracecompass/tmf/core/tests/event/TmfTimestampTest.java
tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/timestamp/TmfNanoTimestamp.java
tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/timestamp/TmfRealTimestamp.java [deleted file]
tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/timestamp/TmfSecondTimestamp.java
tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/timestamp/TmfTimestamp.java
tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/timestamp/TmfTimestampDelta.java

index 998c1f24a3b77ad9a155282a70652ae448914de8..a51ff90bbdce4db1b23e7ebcdc424a0e5cba4c35 100644 (file)
@@ -182,8 +182,7 @@ public class TmfNanoTimestampTest {
     @Test
     public void testNormalizeScaleNot0() {
         ITmfTimestamp ts = ts0.normalize(0, 1);
-        assertEquals("getValue", 0, ts.getValue());
-        assertEquals("getscale", 1, ts.getScale());
+        assertEquals("Zero", TmfTimestamp.ZERO, ts);
 
         ts = ts0.normalize(12345, 1);
         assertEquals("getValue", 12345, ts.getValue());
index 838b1b202f778ecb52e2255357f6926d51cf13c2..dd18f042b85c6a257f35a7cdd2f6985342cb2ead 100644 (file)
@@ -144,8 +144,7 @@ public class TmfSecondTimestampTest {
     @Test
     public void testNormalizeScaleNot0() {
         ITmfTimestamp ts = ts0.normalize(0, 1);
-        assertEquals("getValue", 0, ts.getValue());
-        assertEquals("getscale", 1, ts.getScale());
+        assertEquals("Zero test", TmfTimestamp.ZERO, ts);
 
         ts = ts0.normalize(12345, 1);
         assertEquals("getValue", 12345, ts.getValue());
index 1a0c1333ee38cc40d33989e6c069476c4932be8c..9b6ad134c6c297abe86d274689c45b3906d4d0f7 100644 (file)
@@ -291,13 +291,35 @@ public class TmfTimestampTest {
 
     @Test
     public void testNormalizeScale() {
+        ITmfTimestamp ts = ts1.normalize(0, 3);
+        assertEquals("getValue", 12, ts.getValue());
+        assertEquals("getscale", 3, ts.getScale());
+
+        ts = ts1.normalize(0, -3);
+        assertEquals("getValue", 12345000L, ts.getValue());
+        assertEquals("getscale", -3, ts.getScale());
+    }
+
+    @Test
+    public void testNormalizeLargeScale() {
+        ITmfTimestamp ts = ts1.normalize(0, 10);
+        assertEquals("getValue", 0, ts.getValue());
+        assertEquals("getscale", 0, ts.getScale());
+
+        ts = ts1.normalize(0, -10);
+        assertEquals("getValue", 123450000000000L, ts.getValue());
+        assertEquals("getscale", -10, ts.getScale());
+    }
+
+    @Test
+    public void testNormalizeZeroScale() {
         ITmfTimestamp ts = ts0.normalize(0, 10);
         assertEquals("getValue", 0, ts.getValue());
-        assertEquals("getscale", 10, ts.getScale());
+        assertEquals("getscale", 0, ts.getScale());
 
         ts = ts0.normalize(0, -10);
         assertEquals("getValue", 0, ts.getValue());
-        assertEquals("getscale", -10, ts.getScale());
+        assertEquals("getscale", 0, ts.getScale());
     }
 
     @Test
@@ -328,19 +350,19 @@ public class TmfTimestampTest {
     public void testNormalizeOffsetAndScale() {
         final int SCALE = 12;
 
-        ITmfTimestamp ts = ts0.normalize(0, SCALE);
+        ITmfTimestamp ts = ts1.normalize(0, SCALE);
         assertEquals("getValue", 0, ts.getValue());
-        assertEquals("getscale", SCALE, ts.getScale());
+        assertEquals("getscale", 0, ts.getScale()); // zeroed
 
-        ts = ts0.normalize(12345, SCALE);
+        ts = ts1.normalize(12345, SCALE);
         assertEquals("getValue", 12345, ts.getValue());
         assertEquals("getscale", SCALE, ts.getScale());
 
-        ts = ts0.normalize(10, SCALE);
+        ts = ts1.normalize(10, SCALE);
         assertEquals("getValue", 10, ts.getValue());
         assertEquals("getscale", SCALE, ts.getScale());
 
-        ts = ts0.normalize(-10, SCALE);
+        ts = ts1.normalize(-10, SCALE);
         assertEquals("getValue", -10, ts.getValue());
         assertEquals("getscale", SCALE, ts.getScale());
     }
@@ -420,14 +442,14 @@ public class TmfTimestampTest {
         final ITmfTimestamp ts0b = TmfTimestamp.create(0, Integer.MAX_VALUE);
         final ITmfTimestamp ts0c = TmfTimestamp.create(Long.MAX_VALUE, Integer.MAX_VALUE);
 
-        assertEquals("compareTo", 1, ts0a.compareTo(ts0b));
-        assertEquals("compareTo", -1, ts0a.compareTo(ts0c));
+        assertTrue("compareTo", ts0a.compareTo(ts0b) > 0);
+        assertTrue("compareTo", ts0a.compareTo(ts0c) < 0);
 
-        assertEquals("compareTo", -1, ts0b.compareTo(ts0a));
-        assertEquals("compareTo", -1, ts0b.compareTo(ts0c));
+        assertTrue("compareTo", ts0b.compareTo(ts0a) < 0);
+        assertTrue("compareTo", ts0b.compareTo(ts0c) < 0);
 
-        assertEquals("compareTo", 1, ts0c.compareTo(ts0a));
-        assertEquals("compareTo", 1, ts0c.compareTo(ts0b));
+        assertTrue("compareTo", ts0c.compareTo(ts0a) > 0);
+        assertTrue("compareTo", ts0c.compareTo(ts0b) > 0);
     }
 
     @Test
@@ -436,19 +458,19 @@ public class TmfTimestampTest {
         final ITmfTimestamp ts0b = TmfTimestamp.create(0, Integer.MAX_VALUE);
         final ITmfTimestamp ts0c = TmfTimestamp.create(Long.MIN_VALUE, Integer.MAX_VALUE);
 
-        assertEquals("compareTo", -1, ts0a.compareTo(ts0b));
-        assertEquals("compareTo", 1, ts0a.compareTo(ts0c));
+        assertTrue("compareTo", ts0a.compareTo(ts0b) < 0);
+        assertTrue("compareTo", ts0a.compareTo(ts0c) > 0);
 
-        assertEquals("compareTo", 1, ts0b.compareTo(ts0a));
-        assertEquals("compareTo", 1, ts0b.compareTo(ts0c));
+        assertTrue("compareTo", ts0b.compareTo(ts0a) > 0);
+        assertTrue("compareTo", ts0b.compareTo(ts0c) > 0);
 
-        assertEquals("compareTo", -1, ts0c.compareTo(ts0a));
-        assertEquals("compareTo", -1, ts0c.compareTo(ts0b));
+        assertTrue("compareTo", ts0c.compareTo(ts0a) < 0);
+        assertTrue("compareTo", ts0c.compareTo(ts0b) < 0);
     }
 
-    @Test
+    @Test(expected = NullPointerException.class)
     public void testCompareToCornerCases4() {
-        assertEquals("compareTo", 1, ts0.compareTo(null));
+        assertTrue("compareTo", ts0.compareTo(null) > 0);
     }
 
     @Test
@@ -495,6 +517,76 @@ public class TmfTimestampTest {
         assertTrue("CompareTo", t3.compareTo(t4) > 0);
     }
 
+    @Test
+    public void testCompareToDifferentScale2() {
+        final ITmfTimestamp t5 = TmfTimestamp.fromSeconds(1);
+        final ITmfTimestamp t6 = TmfTimestamp.fromMillis(1234);
+
+        assertTrue("CompareTo", t5.compareTo(t6) < 0);
+        assertTrue("CompareTo", t6.compareTo(t5) > 0);
+    }
+
+    @Test
+    public void testCompareToSpecials() {
+        ITmfTimestamp ersatzBigBang = TmfTimestamp.create(Long.MIN_VALUE, Integer.MAX_VALUE);
+        ITmfTimestamp ersatzBigCrunch = TmfTimestamp.create(Long.MAX_VALUE, Integer.MAX_VALUE);
+
+        ITmfTimestamp lolo = TmfTimestamp.fromMicros(Long.MIN_VALUE);
+        ITmfTimestamp lo = TmfTimestamp.fromMillis(-100);
+        ITmfTimestamp lohi = TmfTimestamp.fromMicros(100);
+        ITmfTimestamp hilo = TmfTimestamp.fromMillis(Long.MIN_VALUE);
+        ITmfTimestamp hi = TmfTimestamp.fromMillis(100);
+
+        assertTrue("CompareTo", TmfTimestamp.BIG_BANG.compareTo(ts0) < 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_BANG.compareTo(ts1) < 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_BANG.compareTo(ts2) < 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_BANG.compareTo(ts3) < 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_BANG.compareTo(ts4) < 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_BANG.compareTo(TmfTimestamp.fromSeconds(Long.MIN_VALUE)) < 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_BANG.compareTo(ersatzBigBang) < 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_BANG.compareTo(TmfTimestamp.BIG_CRUNCH) < 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_BANG.compareTo(TmfTimestamp.BIG_BANG) == 0);
+        assertTrue("CompareTo", ts0.compareTo(TmfTimestamp.BIG_BANG) > 0);
+        assertTrue("CompareTo", ts1.compareTo(TmfTimestamp.BIG_BANG) > 0);
+        assertTrue("CompareTo", ts2.compareTo(TmfTimestamp.BIG_BANG) > 0);
+        assertTrue("CompareTo", ts3.compareTo(TmfTimestamp.BIG_BANG) > 0);
+        assertTrue("CompareTo", ts4.compareTo(TmfTimestamp.BIG_BANG) > 0);
+        assertTrue("CompareTo", ersatzBigBang.compareTo(TmfTimestamp.BIG_BANG) > 0);
+
+        assertTrue("CompareTo", TmfTimestamp.BIG_CRUNCH.compareTo(ts0) > 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_CRUNCH.compareTo(ts1) > 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_CRUNCH.compareTo(ts2) > 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_CRUNCH.compareTo(ts3) > 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_CRUNCH.compareTo(ts4) > 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_CRUNCH.compareTo(TmfTimestamp.fromSeconds(Long.MIN_VALUE)) > 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_CRUNCH.compareTo(ersatzBigCrunch) > 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_CRUNCH.compareTo(TmfTimestamp.BIG_BANG) > 0);
+        assertTrue("CompareTo", TmfTimestamp.BIG_CRUNCH.compareTo(TmfTimestamp.BIG_CRUNCH) == 0);
+        assertTrue("CompareTo", ts0.compareTo(TmfTimestamp.BIG_CRUNCH) < 0);
+        assertTrue("CompareTo", ts1.compareTo(TmfTimestamp.BIG_CRUNCH) < 0);
+        assertTrue("CompareTo", ts2.compareTo(TmfTimestamp.BIG_CRUNCH) < 0);
+        assertTrue("CompareTo", ts3.compareTo(TmfTimestamp.BIG_CRUNCH) < 0);
+        assertTrue("CompareTo", ts4.compareTo(TmfTimestamp.BIG_CRUNCH) < 0);
+        assertTrue("CompareTo", ersatzBigCrunch.compareTo(TmfTimestamp.BIG_CRUNCH) < 0);
+
+        assertTrue("CompareTo", ersatzBigBang.compareTo(ersatzBigCrunch) < 0);
+        assertTrue("CompareTo", ersatzBigCrunch.compareTo(ersatzBigBang) > 0);
+        assertTrue("CompareTo", ersatzBigBang.compareTo(ersatzBigBang) == 0);
+
+        assertTrue("CompareTo", lolo.compareTo(hi) < 0);
+        assertTrue("CompareTo", hi.compareTo(lolo) > 0);
+        assertTrue("CompareTo", lolo.compareTo(lolo) == 0);
+
+        assertTrue("CompareTo", lo.compareTo(hi) < 0);
+        assertTrue("CompareTo", hi.compareTo(lo) > 0);
+        assertTrue("CompareTo", lo.compareTo(lo) == 0);
+
+        assertTrue("CompareTo", hilo.compareTo(lohi) < 0);
+        assertTrue("CompareTo", lohi.compareTo(hilo) > 0);
+        assertTrue("CompareTo", hilo.compareTo(hilo) == 0);
+
+    }
+
     @Test
     public void testCompareToLargeScale1() {
         final ITmfTimestamp t1 = TmfTimestamp.create(-1, 100);
@@ -502,7 +594,7 @@ public class TmfTimestampTest {
         final ITmfTimestamp t3 = TmfTimestamp.create(1, 100);
         final ITmfTimestamp t4 = TmfTimestamp.create(1000, -100);
 
-        assertEquals("CompareTo", -1, t1.compareTo(t2));
+        assertTrue("CompareTo", t1.compareTo(t2) < 0);
         assertTrue("CompareTo", t1.compareTo(t3) < 0);
         assertTrue("CompareTo", t1.compareTo(t4) < 0);
 
@@ -531,6 +623,15 @@ public class TmfTimestampTest {
         assertEquals("CompareTo", -1, ts0.compareTo(ts0b));
     }
 
+    @Test
+    public void testCompareToLargeScale3() {
+        final ITmfTimestamp ts0a = TmfTimestamp.create(1, Integer.MAX_VALUE);
+        final ITmfTimestamp ts0b = TmfTimestamp.create(2, Integer.MAX_VALUE);
+
+        assertTrue("CompareTo", ts0b.compareTo(ts0a) > 0);
+        assertTrue("CompareTo", ts0a.compareTo(ts0b) < 0);
+    }
+
     // ------------------------------------------------------------------------
     // getDelta
     // ------------------------------------------------------------------------
index 49ea7b197058ab3e8db68c2cb6267e41f3f5d6ee..35c6acac7232a9c99f36e79bd75052928d3c19fe 100644 (file)
@@ -52,35 +52,6 @@ public final class TmfNanoTimestamp extends TmfTimestamp {
         return ITmfTimestamp.NANOSECOND_SCALE;
     }
 
-    // ------------------------------------------------------------------------
-    // ITmfTimestamp
-    // ------------------------------------------------------------------------
-
-    @Override
-    public ITmfTimestamp normalize(final long offset, final int scale) {
-        if (scale == ITmfTimestamp.NANOSECOND_SCALE) {
-            return new TmfNanoTimestamp(saturatedAdd(getValue(), offset));
-        }
-        return super.normalize(offset, scale);
-    }
-
-    @Override
-    public int compareTo(final ITmfTimestamp ts) {
-        if (ts instanceof TmfNanoTimestamp) {
-            final long delta = getValue() - ts.getValue();
-            return (delta == 0) ? 0 : (delta > 0) ? 1 : -1;
-        }
-        return super.compareTo(ts);
-    }
-
-    @Override
-    public ITmfTimestamp getDelta(final ITmfTimestamp ts) {
-        if (ts instanceof TmfNanoTimestamp) {
-            return new TmfTimestampDelta(getValue() - ts.getValue(), ITmfTimestamp.NANOSECOND_SCALE);
-        }
-        return super.getDelta(ts);
-    }
-
     /**
      * @since 2.0
      */
@@ -88,30 +59,4 @@ public final class TmfNanoTimestamp extends TmfTimestamp {
     public long toNanos() {
         return getValue();
     }
-
-    // ------------------------------------------------------------------------
-    // Object
-    // ------------------------------------------------------------------------
-
-    @Override
-    public int hashCode() {
-        return super.hashCode();
-    }
-
-    @Override
-    public boolean equals(final Object other) {
-        if (this == other) {
-            return true;
-        }
-        if (other == null) {
-            return false;
-        }
-        if (!(other instanceof TmfNanoTimestamp)) {
-            return super.equals(other);
-        }
-        final TmfNanoTimestamp ts = (TmfNanoTimestamp) other;
-
-        return compareTo(ts) == 0;
-    }
-
 }
diff --git a/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/timestamp/TmfRealTimestamp.java b/tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/tmf/core/timestamp/TmfRealTimestamp.java
deleted file mode 100644 (file)
index e0ee9e0..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2016 Ericsson
- *
- * All rights reserved. This program and the accompanying materials are
- * made available under the terms of the Eclipse Public License v1.0 which
- * accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *******************************************************************************/
-
-package org.eclipse.tracecompass.tmf.core.timestamp;
-
-/**
- * A timestamp with a user provided scale and value
- *
- * @author Matthew Khouzam
- * @since 2.0
- */
-public class TmfRealTimestamp extends TmfTimestamp {
-
-    // ------------------------------------------------------------------------
-    // Attributes
-    // ------------------------------------------------------------------------
-
-    /**
-     * The timestamp raw value (mantissa)
-     */
-    private final long fValue;
-
-    /**
-     * The timestamp scale (magnitude)
-     */
-    private final int fScale;
-
-    // ------------------------------------------------------------------------
-    // Constructors
-    // ------------------------------------------------------------------------
-
-    /**
-     * Full constructor
-     *
-     * @param value
-     *            the timestamp value
-     * @param scale
-     *            the timestamp scale
-     */
-    public TmfRealTimestamp(final long value, final int scale) {
-        fValue = value;
-        fScale = scale;
-    }
-
-    @Override
-    public long getValue() {
-        return fValue;
-    }
-
-    @Override
-    public int getScale() {
-        return fScale;
-    }
-}
index 8c5b573bcae3cad31adc1afb3df3ab4852705794..cba830804c929e7f4dfe165701ba1c48b1ac61ee 100644 (file)
@@ -53,59 +53,4 @@ public class TmfSecondTimestamp extends TmfTimestamp {
     public long getValue() {
         return fValue;
     }
-
-    // ------------------------------------------------------------------------
-    // ITmfTimestamp
-    // ------------------------------------------------------------------------
-
-    @Override
-    public ITmfTimestamp normalize(final long offset, final int scale) {
-        if (scale == ITmfTimestamp.SECOND_SCALE) {
-            return TmfTimestamp.fromSeconds(saturatedAdd(getValue(), offset));
-        }
-        return super.normalize(offset, scale);
-    }
-
-    @Override
-    public int compareTo(final ITmfTimestamp ts) {
-        if (ts instanceof TmfSecondTimestamp) {
-            final long delta = getValue() - ts.getValue();
-            return (delta == 0) ? 0 : (delta > 0) ? 1 : -1;
-        }
-        return super.compareTo(ts);
-    }
-
-    @Override
-    public ITmfTimestamp getDelta(final ITmfTimestamp ts) {
-        if (ts instanceof TmfSecondTimestamp) {
-            return new TmfTimestampDelta(getValue() - ts.getValue());
-        }
-        return super.getDelta(ts);
-    }
-
-    // ------------------------------------------------------------------------
-    // Object
-    // ------------------------------------------------------------------------
-
-    @Override
-    public int hashCode() {
-        return super.hashCode();
-    }
-
-    @Override
-    public boolean equals(final Object other) {
-        if (this == other) {
-            return true;
-        }
-        if (other == null) {
-            return false;
-        }
-        if (!(other instanceof TmfSecondTimestamp)) {
-            return super.equals(other);
-        }
-        final TmfSecondTimestamp ts = (TmfSecondTimestamp) other;
-
-        return compareTo(ts) == 0;
-    }
-
 }
index a12eb9d9d31d7e10fe1d8689152f0349a3df5387..141d7a33440f3adcfa074b5bd0c6e45a6cb811cb 100644 (file)
@@ -26,6 +26,57 @@ import org.eclipse.jdt.annotation.NonNull;
  * @author Francois Chouinard
  */
 public abstract class TmfTimestamp implements ITmfTimestamp {
+
+    /**
+     * Default implementation of the tmf timestamp. We want this to be hidden.
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    private static final class Impl extends TmfTimestamp {
+
+        // ------------------------------------------------------------------------
+        // Attributes
+        // ------------------------------------------------------------------------
+
+        /**
+         * The timestamp raw value (mantissa)
+         */
+        private final long fValue;
+
+        /**
+         * The timestamp scale (magnitude)
+         */
+        private final int fScale;
+
+        // ------------------------------------------------------------------------
+        // Constructors
+        // ------------------------------------------------------------------------
+
+        /**
+         * Full constructor
+         *
+         * @param value
+         *            the timestamp value
+         * @param scale
+         *            the timestamp scale
+         */
+        public Impl(final long value, final int scale) {
+            fValue = value;
+            fScale = scale;
+        }
+
+        @Override
+        public long getValue() {
+            return fValue;
+        }
+
+        @Override
+        public int getScale() {
+            return fScale;
+        }
+    }
+
     /**
      * Create a timestamp.
      *
@@ -105,6 +156,9 @@ public abstract class TmfTimestamp implements ITmfTimestamp {
         if (scale == ITmfTimestamp.SECOND_SCALE) {
             return fromSeconds(value);
         }
+        if (value == 0) {
+            return ZERO;
+        }
         return createOther(value, scale);
     }
 
@@ -123,7 +177,7 @@ public abstract class TmfTimestamp implements ITmfTimestamp {
     }
 
     private static @NonNull ITmfTimestamp createOther(long value, int scale) {
-        return new TmfRealTimestamp(value, scale);
+        return new Impl(value, scale);
     }
 
     // ------------------------------------------------------------------------
@@ -131,19 +185,99 @@ public abstract class TmfTimestamp implements ITmfTimestamp {
     // ------------------------------------------------------------------------
 
     /**
-     * The beginning of time
+     * Zero - a zero time constant. The value is zero, so this allows some
+     * interesting simplifications.
      */
-    public static final @NonNull ITmfTimestamp BIG_BANG = new TmfRealTimestamp(Long.MIN_VALUE, Integer.MAX_VALUE);
+    public static final @NonNull ITmfTimestamp ZERO = new TmfTimestamp() {
+        @Override
+        public long getValue() {
+            return 0;
+        }
+
+        @Override
+        public int getScale() {
+            return 0;
+        }
+
+        @Override
+        public @NonNull ITmfTimestamp normalize(long offset, int scale) {
+            if (offset == 0) {
+                return this;
+            }
+            return create(offset, scale);
+        }
+
+        @Override
+        public int compareTo(ITmfTimestamp ts) {
+            return Long.compare(0, ts.getValue());
+        }
+    };
 
     /**
-     * The end of time
+     * The beginning of time will be lesser than any other timestamp
      */
-    public static final @NonNull ITmfTimestamp BIG_CRUNCH = new TmfRealTimestamp(Long.MAX_VALUE, Integer.MAX_VALUE);
+    public static final @NonNull ITmfTimestamp BIG_BANG = new TmfTimestamp() {
+        @Override
+        public long getValue() {
+            return Long.MIN_VALUE;
+        }
+
+        @Override
+        public int getScale() {
+            return Integer.MAX_VALUE;
+        }
+
+        @Override
+        public int compareTo(ITmfTimestamp other) {
+            if (equals(other) == true) {
+                return 0;
+            }
+            return -1;
+        }
+
+        @Override
+        public ITmfTimestamp normalize(long offset, int scale) {
+            return this;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this == other;
+        }
+    };
 
     /**
-     * Zero
+     * The end of time will be greater than any other timestamp
      */
-    public static final @NonNull ITmfTimestamp ZERO = new TmfRealTimestamp(0, 0);
+    public static final @NonNull ITmfTimestamp BIG_CRUNCH = new TmfTimestamp() {
+        @Override
+        public long getValue() {
+            return Long.MAX_VALUE;
+        }
+
+        @Override
+        public int getScale() {
+            return Integer.MAX_VALUE;
+        }
+
+        @Override
+        public int compareTo(ITmfTimestamp other) {
+            if (equals(other) == true) {
+                return 0;
+            }
+            return 1;
+        }
+
+        @Override
+        public ITmfTimestamp normalize(long offset, int scale) {
+            return this;
+        }
+
+        @Override
+        public boolean equals(Object other) {
+            return this == other;
+        }
+    };
 
     // ------------------------------------------------------------------------
     // ITmfTimestamp
@@ -186,12 +320,6 @@ public abstract class TmfTimestamp implements ITmfTimestamp {
             return this;
         }
 
-        // In case of big bang and big crunch just return this (no need to
-        // normalize)
-        if (this.equals(BIG_BANG) || this.equals(BIG_CRUNCH)) {
-            return this;
-        }
-
         if (value == 0) {
             return create(offset, scale);
         }
@@ -247,40 +375,48 @@ public abstract class TmfTimestamp implements ITmfTimestamp {
         int scale = getScale();
         // Check the corner cases (we can't use equals() because it uses
         // compareTo()...)
-        if (ts == null) {
+        if (BIG_BANG.equals(ts)) {
             return 1;
         }
-        if (this == ts || (value == ts.getValue() && scale == ts.getScale())) {
-            return 0;
-        }
-        if ((value == BIG_BANG.getValue() && scale == BIG_BANG.getScale()) || (ts.getValue() == BIG_CRUNCH.getValue() && ts.getScale() == BIG_CRUNCH.getScale())) {
+
+        if (BIG_CRUNCH.equals(ts)) {
             return -1;
         }
-        if ((value == BIG_CRUNCH.getValue() && scale == BIG_CRUNCH.getScale()) || (ts.getValue() == BIG_BANG.getValue() && ts.getScale() == BIG_BANG.getScale())) {
-            return 1;
+
+        if (this == ts || isIdentical(this, ts)) {
+            return 0;
         }
-        final ITmfTimestamp nts = ts.normalize(0, scale);
-        if ((nts.getValue() == 0 && ts.getValue() != 0) || (ts.getValue() != Long.MAX_VALUE && nts.getValue() == Long.MAX_VALUE) || (ts.getValue() != Long.MIN_VALUE && nts.getValue() == Long.MIN_VALUE)) {
-            // Scaling error. We can figure it out nonetheless.
 
-            // First, look at the sign of the mantissa
-            final long otherValue = ts.getValue();
-            if (value == 0 && otherValue == 0) {
-                return 0;
-            }
-            if (value < 0 && otherValue >= 0) {
-                return -1;
-            }
-            if (value >= 0 && otherValue < 0) {
+        if (scale == ts.getScale()) {
+            if (ts.getValue() == Long.MIN_VALUE) {
                 return 1;
             }
-
-            // Otherwise, just compare the scales
-            final int otherScale = ts.getScale();
-            return (scale > otherScale) ? (otherValue >= 0) ? 1 : -1 : (otherValue >= 0) ? -1 : 1;
+            final long delta = saturatedAdd(getValue(), -ts.getValue());
+            return Long.compare(delta, 0);
+        }
+        final ITmfTimestamp largerScale = (scale > ts.getScale()) ? this : ts;
+        final ITmfTimestamp smallerScale = (scale < ts.getScale()) ? this : ts;
+
+        final ITmfTimestamp nts = largerScale.normalize(0, smallerScale.getScale());
+        if (hasSaturated(largerScale, nts)) {
+            // We've saturated largerScale.
+            if (smallerScale.getScale() == scale) {
+                return Long.compare(0, nts.getValue());
+            }
+            return Long.compare(nts.getValue(), 0);
         }
-        final long delta = value - nts.getValue();
-        return Long.compare(delta, 0);
+        if (smallerScale.getScale() == scale) {
+            return Long.compare(value, nts.getValue());
+        }
+        return Long.compare(nts.getValue(), smallerScale.getValue());
+    }
+
+    private static boolean hasSaturated(final ITmfTimestamp ts, final ITmfTimestamp nts) {
+        return (nts.getValue() == 0 && ts.getValue() != 0) || !isIdentical(ts, nts) && ((nts.getValue() == Long.MAX_VALUE) || (nts.getValue() == Long.MIN_VALUE));
+    }
+
+    private static boolean isIdentical(final ITmfTimestamp ts, final ITmfTimestamp nts) {
+        return ts.getValue() == nts.getValue() && ts.getScale() == nts.getScale();
     }
 
     /**
@@ -360,6 +496,9 @@ public abstract class TmfTimestamp implements ITmfTimestamp {
         }
         /* We allow comparing with other types of *I*TmfTimestamp though */
         final ITmfTimestamp ts = (ITmfTimestamp) other;
+        if (getScale() == ts.getScale()) {
+            return getValue() == ts.getValue();
+        }
         return (compareTo(ts) == 0);
     }
 
index 275bf233bb16ab2c7ecb2375b8f5bd499f41604c..452163819b3f55581a28c4dab8636e6cac07b4c2 100644 (file)
@@ -19,12 +19,15 @@ import java.util.TimeZone;
  *
  * @author Bernd Hufmann
  */
-public class TmfTimestampDelta extends TmfRealTimestamp {
+public class TmfTimestampDelta extends TmfTimestamp {
 
     // ------------------------------------------------------------------------
     // Members
     // ------------------------------------------------------------------------
 
+    private final long fValue;
+    private final int fScale;
+
     // ------------------------------------------------------------------------
     // Constructors
     // ------------------------------------------------------------------------
@@ -32,7 +35,7 @@ public class TmfTimestampDelta extends TmfRealTimestamp {
      * Default constructor
      */
     public TmfTimestampDelta() {
-        super(0, ITmfTimestamp.SECOND_SCALE);
+        this(0, ITmfTimestamp.SECOND_SCALE);
     }
 
     /**
@@ -43,7 +46,7 @@ public class TmfTimestampDelta extends TmfRealTimestamp {
      */
 
     public TmfTimestampDelta(long value) {
-        super(value, ITmfTimestamp.SECOND_SCALE);
+        this(value, ITmfTimestamp.SECOND_SCALE);
     }
 
     /**
@@ -55,7 +58,8 @@ public class TmfTimestampDelta extends TmfRealTimestamp {
      *            the timestamp scale
      */
     public TmfTimestampDelta(long value, int scale) {
-        super(value, scale);
+        fValue = value;
+        fScale = scale;
     }
 
     /**
@@ -65,13 +69,23 @@ public class TmfTimestampDelta extends TmfRealTimestamp {
      *            the timestamp to copy
      */
     public TmfTimestampDelta(ITmfTimestamp timestamp) {
-        super(timestamp.getValue(), timestamp.getScale());
+        this(timestamp.getValue(), timestamp.getScale());
     }
 
     // ------------------------------------------------------------------------
     // Operations
     // ------------------------------------------------------------------------
 
+    @Override
+    public long getValue() {
+        return fValue;
+    }
+
+    @Override
+    public int getScale() {
+        return fScale;
+    }
+
     @Override
     public ITmfTimestamp normalize(final long offset, final int scale) {
         ITmfTimestamp nts = super.normalize(offset, scale);
This page took 0.044584 seconds and 5 git commands to generate.