killbill-memoizeit

Yet another pass at reordering the timeline events for when

11/11/2013 10:38:25 PM

Details

diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionBundleTimeline.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionBundleTimeline.java
index 060a5e0..796eb06 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionBundleTimeline.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/DefaultSubscriptionBundleTimeline.java
@@ -177,10 +177,12 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
                 while (currentIndex >= 1) {
                     final DefaultSubscriptionEvent revCur = (DefaultSubscriptionEvent) events.get(currentIndex);
                     final DefaultSubscriptionEvent other = (DefaultSubscriptionEvent) events.get(currentIndex - 1);
-                    if (!shouldSwap(revCur, other, false)) {
+                    if (shouldSwap(revCur, other, false)) {
+                        Collections.swap(events, currentIndex, currentIndex - 1);
+                    }
+                    if (revCur.getEffectiveDate().compareTo(other.getEffectiveDate()) != 0) {
                         break;
                     }
-                    Collections.swap(events, currentIndex, currentIndex - 1);
                     currentIndex--;
                 }
             }
@@ -190,10 +192,15 @@ public class DefaultSubscriptionBundleTimeline implements SubscriptionBundleTime
 
     private boolean shouldSwap(DefaultSubscriptionEvent cur, DefaultSubscriptionEvent other, boolean isAscending) {
 
-        return (cur.getEffectiveDateTime().compareTo(other.getEffectiveDateTime()) == 0 &&
-                cur.getEntitlementId().equals(other.getEntitlementId()) &&
-                ((isAscending && cur.getSubscriptionEventType().ordinal() > other.getSubscriptionEventType().ordinal()) ||
-                 (!isAscending && cur.getSubscriptionEventType().ordinal() < other.getSubscriptionEventType().ordinal())));
+        // For a given date, order by subscriptionId, and within subscription by event type
+        final int idComp = cur.getEntitlementId().compareTo(other.getEntitlementId());
+        return (cur.getEffectiveDate().compareTo(other.getEffectiveDate()) == 0 &&
+                ((isAscending &&
+                  ((idComp > 0) ||
+                   (idComp == 0 && cur.getSubscriptionEventType().ordinal() > other.getSubscriptionEventType().ordinal()))) ||
+                (!isAscending &&
+                   ((idComp < 0) ||
+                    (idComp == 0 && cur.getSubscriptionEventType().ordinal() < other.getSubscriptionEventType().ordinal())))));
     }
 
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultSubscriptionBundleTimeline.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultSubscriptionBundleTimeline.java
index 7e950d0..359f73c 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultSubscriptionBundleTimeline.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestDefaultSubscriptionBundleTimeline.java
@@ -152,6 +152,61 @@ public class TestDefaultSubscriptionBundleTimeline extends EntitlementTestSuiteN
 
 
     @Test(groups = "fast")
+    public void testReOrderSubscriptionEventsOnInvalidOrderAndDifferentSubscriptionsSameDates1() {
+        TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
+
+        final List<SubscriptionEvent> events = new ArrayList<SubscriptionEvent>();
+        final UUID subscriptionId = UUID.fromString("60b64e0c-cefd-48c3-8de9-c731a9558165");
+
+        final UUID otherSubscriptionId = UUID.fromString("35b3b340-31b2-46ea-b062-e9fc9fab3bc9");
+        final DateTime effectiveDate = clock.getUTCNow();
+
+        events.add(timeline.createEvent(subscriptionId, SubscriptionEventType.START_ENTITLEMENT, effectiveDate));
+        events.add(timeline.createEvent(subscriptionId, SubscriptionEventType.START_BILLING, effectiveDate));
+        events.add(timeline.createEvent(subscriptionId, SubscriptionEventType.STOP_BILLING, effectiveDate));
+        events.add(timeline.createEvent(otherSubscriptionId, SubscriptionEventType.STOP_BILLING, effectiveDate));
+        events.add(timeline.createEvent(subscriptionId, SubscriptionEventType.STOP_ENTITLEMENT, effectiveDate));
+
+        timeline.reOrderSubscriptionEventsOnSameDateByType(events);
+
+        Assert.assertEquals(events.get(0).getSubscriptionEventType(), SubscriptionEventType.STOP_BILLING);
+        Assert.assertEquals(events.get(0).getEntitlementId(), otherSubscriptionId);
+        Assert.assertEquals(events.get(1).getSubscriptionEventType(), SubscriptionEventType.START_ENTITLEMENT);
+        Assert.assertEquals(events.get(2).getSubscriptionEventType(), SubscriptionEventType.START_BILLING);
+        Assert.assertEquals(events.get(3).getSubscriptionEventType(), SubscriptionEventType.STOP_ENTITLEMENT);
+        Assert.assertEquals(events.get(4).getSubscriptionEventType(), SubscriptionEventType.STOP_BILLING);
+        Assert.assertEquals(events.get(4).getEntitlementId(), subscriptionId);
+    }
+
+    @Test(groups = "fast")
+    public void testReOrderSubscriptionEventsOnInvalidOrderAndDifferentSubscriptionsSameDates2() {
+        TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());
+
+        final List<SubscriptionEvent> events = new ArrayList<SubscriptionEvent>();
+        final UUID subscriptionId = UUID.fromString("35b3b340-31b2-46ea-b062-e9fc9fab3bc9");
+        final UUID otherSubscriptionId = UUID.fromString("60b64e0c-cefd-48c3-8de9-c731a9558165");
+
+        final DateTime effectiveDate = clock.getUTCNow();
+
+        events.add(timeline.createEvent(subscriptionId, SubscriptionEventType.START_ENTITLEMENT, effectiveDate));
+        events.add(timeline.createEvent(subscriptionId, SubscriptionEventType.START_BILLING, effectiveDate));
+        events.add(timeline.createEvent(subscriptionId, SubscriptionEventType.STOP_BILLING, effectiveDate));
+        events.add(timeline.createEvent(otherSubscriptionId, SubscriptionEventType.STOP_BILLING, effectiveDate));
+        events.add(timeline.createEvent(subscriptionId, SubscriptionEventType.STOP_ENTITLEMENT, effectiveDate));
+
+        timeline.reOrderSubscriptionEventsOnSameDateByType(events);
+
+        Assert.assertEquals(events.get(0).getSubscriptionEventType(), SubscriptionEventType.START_ENTITLEMENT);
+        Assert.assertEquals(events.get(1).getSubscriptionEventType(), SubscriptionEventType.START_BILLING);
+        Assert.assertEquals(events.get(2).getSubscriptionEventType(), SubscriptionEventType.STOP_ENTITLEMENT);
+        Assert.assertEquals(events.get(3).getSubscriptionEventType(), SubscriptionEventType.STOP_BILLING);
+        Assert.assertEquals(events.get(3).getEntitlementId(), subscriptionId);
+        Assert.assertEquals(events.get(4).getSubscriptionEventType(), SubscriptionEventType.STOP_BILLING);
+        Assert.assertEquals(events.get(4).getEntitlementId(), otherSubscriptionId);
+
+    }
+
+    @Test(groups = "fast")
     public void testReOrderSubscriptionEventsOnInvalidOrderAndDifferentSubscriptionsDates() {
         TestSubscriptionBundleTimeline timeline = new TestSubscriptionBundleTimeline(null, null, null, null, new ArrayList<Entitlement>(), new ArrayList<BlockingState>());