killbill-uncached

Details

beatrix/pom.xml 5(+5 -0)

diff --git a/beatrix/pom.xml b/beatrix/pom.xml
index da3f0e6..0e5dc26 100644
--- a/beatrix/pom.xml
+++ b/beatrix/pom.xml
@@ -102,6 +102,11 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-overdue</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.jdbi</groupId>
             <artifactId>jdbi</artifactId>
             <scope>test</scope>
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
new file mode 100644
index 0000000..2dfe2ee
--- /dev/null
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/overdue/TestOverdueIntegration.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+//package com.ning.billing.beatrix.integration.overdue;
+//
+//import static org.testng.Assert.assertNotNull;
+//
+//import java.io.ByteArrayInputStream;
+//import java.io.InputStream;
+//
+//import org.joda.time.DateTime;
+//import org.joda.time.Interval;
+//
+//import com.google.inject.Inject;
+//import com.ning.billing.account.api.Account;
+//import com.ning.billing.beatrix.integration.TestIntegrationBase;
+//import com.ning.billing.catalog.api.BillingPeriod;
+//import com.ning.billing.catalog.api.Duration;
+//import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+//import com.ning.billing.catalog.api.PriceListSet;
+//import com.ning.billing.catalog.api.ProductCategory;
+//import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+//import com.ning.billing.entitlement.api.user.SubscriptionData;
+//import com.ning.billing.junction.api.BlockingApi;
+//import com.ning.billing.overdue.config.OverdueConfig;
+//import com.ning.billing.payment.provider.MockPaymentProviderPlugin;
+//import com.ning.billing.util.clock.ClockMock;
+//import com.ning.billing.util.config.XMLLoader;
+//
+//public class TestOverdueIntegration extends TestIntegrationBase {
+//    private final String configXml =  
+//            "<overdueConfig>" +
+//                    "   <bundleOverdueStates>" +
+//                    "       <state name=\"OD1\">" +
+//                    "           <condition>" +
+//                    "               <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+//                    "                   <unit>MONTHS</unit><number>1</number>" +
+//                    "               </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+//                    "           </condition>" +
+//                    "           <externalMessage>Reached OD1</externalMessage>" +
+//                    "           <blockChanges>true</blockChanges>" +
+//                    "           <disableEntitlementAndChangesBlocked>false</disableEntitlementAndChangesBlocked>" +
+//                    "       </state>" +
+//                    "       <state name=\"OD2\">" +
+//                    "           <condition>" +
+//                    "               <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+//                    "                   <unit>MONTHS</unit><number>2</number>" +
+//                    "               </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+//                    "           </condition>" +
+//                    "           <externalMessage>Reached OD1</externalMessage>" +
+//                    "           <blockChanges>true</blockChanges>" +
+//                    "           <disableEntitlementAndChangesBlocked>true</disableEntitlementAndChangesBlocked>" +
+//                    "       </state>" +
+//                    "   </bundleOverdueStates>" +
+//                    "</overdueConfig>";
+//    private OverdueConfig config; 
+//    
+//    @Inject
+//    private ClockMock clock;
+//    
+//    @Inject
+//    private MockPaymentProviderPlugin paymentPlugin;
+//    
+//    @Inject
+//    private BlockingApi blockingApi;
+//    
+//    private Account account;
+//    private SubscriptionBundle bundle;
+//    private String productName;
+//    private BillingPeriod term;
+//    private String planSetName;
+//
+//    long twoWeeks = new Interval(clock.getUTCNow(), clock.getUTCNow().plusWeeks(2)).toDurationMillis();
+//    long fourWeeks = new Interval(clock.getUTCNow(), clock.getUTCNow().plusWeeks(4)).toDurationMillis();
+//    
+//    //@BeforeMethod
+//    public void setup() throws Exception {
+//        InputStream is = new ByteArrayInputStream(configXml.getBytes());
+//        config = XMLLoader.getObjectFromStreamNoValidation(is,  OverdueConfig.class);
+//        Account account = accountUserApi.createAccount(getAccountData(25), null, null, context);
+//        assertNotNull(account);
+//
+//        bundle = entitlementUserApi.createBundleForAccount(account.getId(), "whatever", context);
+//
+//        productName = "Shotgun";
+//        term = BillingPeriod.MONTHLY;
+//        planSetName = PriceListSet.DEFAULT_PRICELIST_NAME;
+//        
+//        // create account
+//        // set mock payments to fail
+//        // reset clock
+//        // configure basic OD state rules for 2 states OD1 1-2month, OD2 2-3 month
+//    }
+//    
+//    //@AfterMethod
+//    public void cleanup(){
+//        // Clear databases
+//    }
+//    
+//    public void testBasicOverdueState() throws Exception {
+//        DateTime initialDate = new DateTime(2012, 4, 25, 0, 3, 42, 0);
+//        clock.setDeltaFromReality(initialDate.getMillis() - clock.getUTCNow().getMillis());
+//        
+//        
+//        // set next invoice to fail and create network 
+//        paymentPlugin.makeNextInvoiceFail();
+//        SubscriptionData baseSubscription = subscriptionDataFromSubscription(entitlementUserApi.createSubscription(bundle.getId(),
+//                new PlanPhaseSpecifier(productName, ProductCategory.BASE, term, planSetName, null), null, context));
+//        assertNotNull(baseSubscription);
+//
+//
+//       // advance time 2weeks
+//        clock.addDeltaFromReality(twoWeeks);
+//        
+//       // should still be in clear state
+//       blockingApi.getBlockingStateFor(bundle);
+//        
+//       // set next invoice to fail and advance time 1 month
+//       clock.addDeltaFromReality(fourWeeks);
+//       
+//       // should now be in OD1 state
+//       // set next invoice to fail and advance time 1 month
+//       // should now be in OD2 state
+//
+//        
+//    }
+//}
diff --git a/bin/clean-and-install b/bin/clean-and-install
new file mode 100755
index 0000000..c6c3ac4
--- /dev/null
+++ b/bin/clean-and-install
@@ -0,0 +1,22 @@
+#! /usr/bin/env bash
+
+###################################################################################
+#                                                                                 #
+#                   Copyright 2010-2011 Ning, Inc.                                #
+#                                                                                 #
+#      Ning licenses this file to you under the Apache License, version 2.0       #
+#      (the "License"); you may not use this file except in compliance with the   #
+#      License.  You may obtain a copy of the License at:                         #
+#                                                                                 #
+#          http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                                 #
+#      Unless required by applicable law or agreed to in writing, software        #
+#      distributed under the License is distributed on an "AS IS" BASIS, WITHOUT  #
+#      WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the  #
+#      License for the specific language governing permissions and limitations    #
+#      under the License.                                                         #
+#                                                                                 #
+###################################################################################
+
+bin/db-helper -a clean -d killbill; 
+mvn -Dcom.ning.billing.dbi.test.useLocalDb=true clean install 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java
index 0d7aed7..e1f6c28 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/migration/TestMigration.java
@@ -161,6 +161,7 @@ public abstract class TestMigration extends TestApiBase {
             assertEquals(subscription.getCurrentPlan().getName(), "assault-rifle-annual");
             assertEquals(subscription.getChargedThroughDate(), startDate.plusYears(1));
 
+
             testListener.pushExpectedEvent(NextEvent.MIGRATE_BILLING);
             testListener.pushExpectedEvent(NextEvent.CANCEL);
             
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
index f3ea92a..7d1389e 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
@@ -382,7 +382,7 @@ public abstract class TestApiBase implements TestListenerStatus {
 
             @Override
             public DateTime addToDateTime(DateTime dateTime) {
-                return null;  //To change body of implemented methods use File | Settings | File Templates.
+                return dateTime.plusYears(years);  
             }
             @Override
             public Period toJodaPeriod() {
diff --git a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java
index 7d84e7c..9a448c2 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/config/DefaultOverdueState.java
@@ -42,12 +42,12 @@ public class DefaultOverdueState<T extends Blockable> extends ValidatingConfig<O
 
 	@XmlElement(required=false, name="externalMessage")
 	private String externalMessage = "";
-
-    @XmlElement(required=false, name="disableEntitlementAndChangesBlocked")
-    private Boolean disableEntitlement = false;
     
     @XmlElement(required=false, name="blockChanges")
     private Boolean blockChanges = false;
+
+    @XmlElement(required=false, name="disableEntitlementAndChangesBlocked")
+    private Boolean disableEntitlement = false;
     
     @XmlElement(required=false, name="daysBetweenPaymentRetries")
     private Integer daysBetweenPaymentRetries = 8;
diff --git a/overdue/src/test/java/com/ning/billing/overdue/config/TestOverdueConfig.java b/overdue/src/test/java/com/ning/billing/overdue/config/TestOverdueConfig.java
new file mode 100644
index 0000000..df4f4c3
--- /dev/null
+++ b/overdue/src/test/java/com/ning/billing/overdue/config/TestOverdueConfig.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.overdue.config;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.testng.annotations.Test;
+
+import com.ning.billing.util.config.XMLLoader;
+
+public class TestOverdueConfig {
+    private String xml = 
+            "<overdueConfig>" +
+                    "   <bundleOverdueStates>" +
+                    "       <state name=\"OD1\">" +
+                    "           <condition>" +
+                    "               <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+                    "                   <unit>MONTHS</unit><number>1</number>" +
+                    "               </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+                    "           </condition>" +
+                    "           <externalMessage>Reached OD1</externalMessage>" +
+                    "           <blockChanges>true</blockChanges>" +
+                    "           <disableEntitlementAndChangesBlocked>false</disableEntitlementAndChangesBlocked>" +
+                    "       </state>" +
+                    "       <state name=\"OD2\">" +
+                    "           <condition>" +
+                    "               <timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+                    "                   <unit>MONTHS</unit><number>2</number>" +
+                    "               </timeSinceEarliestUnpaidInvoiceEqualsOrExceeds>" +
+                    "           </condition>" +
+                    "           <externalMessage>Reached OD1</externalMessage>" +
+                    "           <blockChanges>true</blockChanges>" +
+                    "           <disableEntitlementAndChangesBlocked>true</disableEntitlementAndChangesBlocked>" +
+                    "       </state>" +
+                    "   </bundleOverdueStates>" +
+                    "</overdueConfig>";
+
+    @Test
+    public void testParseConfig() throws Exception {
+        InputStream is = new ByteArrayInputStream(xml.getBytes());
+        OverdueConfig c = XMLLoader.getObjectFromStreamNoValidation(is,  OverdueConfig.class);
+
+    }
+
+}

pom.xml 12(+12 -0)

diff --git a/pom.xml b/pom.xml
index 02b1aa6..7fe6a40 100644
--- a/pom.xml
+++ b/pom.xml
@@ -176,6 +176,18 @@
             </dependency>
             <dependency>
                 <groupId>com.ning.billing</groupId>
+                <artifactId>killbill-overdue</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>com.ning.billing</groupId>
+                <artifactId>killbill-overdue</artifactId>
+                <version>${project.version}</version>
+                <type>test-jar</type>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>com.ning.billing</groupId>
                 <artifactId>killbill-util</artifactId>
                 <version>${project.version}</version>
                 <type>test-jar</type>
diff --git a/util/src/test/java/com/ning/billing/util/clock/ClockMock.java b/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
index 9e51a80..ab702cb 100644
--- a/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
+++ b/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
@@ -16,147 +16,134 @@
 
 package com.ning.billing.util.clock;
 
-import com.ning.billing.catalog.api.Duration;
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
+import org.joda.time.Days;
+import org.joda.time.Months;
+import org.joda.time.MutablePeriod;
+import org.joda.time.Period;
+import org.joda.time.ReadablePeriod;
+import org.joda.time.Weeks;
+import org.joda.time.Years;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.List;
-
-// STEPH should really be in tests but not accessible from other sub modules
-public class ClockMock extends DefaultClock {
+import com.ning.billing.catalog.api.Duration;
+import com.ning.billing.catalog.api.TimeUnit;
 
+public class ClockMock implements Clock {
+    
+    private MutablePeriod delta = new MutablePeriod();
     private static final Logger log = LoggerFactory.getLogger(ClockMock.class);
 
-    private enum DeltaType {
-        DELTA_NONE,
-        DELTA_DURATION,
-        DELTA_ABS
-    }
-
-    private long deltaFromRealityMs;
-    private List<Duration> deltaFromRealityDuration;
-    private long deltaFromRealityDurationEpsilon;
-    private DeltaType deltaType;
-
-    public ClockMock() {
-        deltaType = DeltaType.DELTA_NONE;
-        deltaFromRealityMs = 0;
-        deltaFromRealityDurationEpsilon = 0;
-        deltaFromRealityDuration = null;
-    }
-
+     
     @Override
     public synchronized DateTime getNow(DateTimeZone tz) {
-        return adjust(super.getNow(tz));
+        return getUTCNow().toDateTime(tz);
     }
 
     @Override
     public synchronized DateTime getUTCNow() {
-        return getNow(DateTimeZone.UTC);
+        return truncate(adjust(now()));
+    }
+    
+    private DateTime adjust(DateTime now) {
+        return now.plus(delta);
     }
 
-    private void logClockAdjustment(DateTime prev, DateTime next) {
-        log.info(String.format("            ************      ADJUSTING CLOCK FROM %s to %s     ********************", prev, next));
+    public synchronized void setTime(DateTime time) {
+        DateTime prev = getUTCNow();
+        delta = new MutablePeriod(now(), time);
+        logChange(prev);
+    }
+    
+    public synchronized void addDays(int days) {
+        adjustTo(Days.days(days));
+    }
+    
+    public synchronized void addWeeks(int weeks) {
+        adjustTo(Weeks.weeks(weeks));
+    }
+    
+    public synchronized void addMonths(int months) {
+        adjustTo(Months.months(months));
+    }
+    
+    public synchronized void addYears(int years) {
+        adjustTo(Years.years(years));
+    }
+    
+    public synchronized void reset() {
+        delta = new MutablePeriod();
+    }
+    
+    @Override
+    public String toString() {
+        return getUTCNow().toString();
+    }
+    
+    private void adjustTo(ReadablePeriod period) {
+        DateTime prev = getUTCNow();
+        delta.add(period);
+        logChange(prev);
+    }
+    
+    private void logChange(DateTime prev) {     
+        DateTime now = getUTCNow();
+        log.info(String.format("            ************      ADJUSTING CLOCK FROM %s to %s     ********************", prev, now));
+    }
+    
+    private DateTime now() {
+        return new DateTime(DateTimeZone.UTC);
     }
 
-    public synchronized void setDeltaFromReality(Duration delta, long epsilon) {
+    private DateTime truncate(DateTime time) {
+        return time.minus(time.getMillisOfSecond());
+    }
+   
+    //
+    //Backward compatibility stuff
+    //
+    public synchronized void setDeltaFromReality(Duration duration, long epsilon) {
         DateTime prev = getUTCNow();
-        deltaType = DeltaType.DELTA_DURATION;
-        deltaFromRealityDuration = new ArrayList<Duration>();
-        deltaFromRealityDuration.add(delta);
-        deltaFromRealityDurationEpsilon = epsilon;
-        deltaFromRealityMs = 0;
-        logClockAdjustment(prev, getUTCNow());
+        delta.addMillis((int)epsilon);
+        addDeltaFromReality(duration);
+        logChange(prev);
+        
     }
 
     public synchronized void addDeltaFromReality(Duration delta) {
-        DateTime prev = getUTCNow();
-        if (deltaType != DeltaType.DELTA_DURATION) {
-            throw new RuntimeException("ClockMock should be set with type DELTA_DURATION");
-        }
-        deltaFromRealityDuration.add(delta);
-        logClockAdjustment(prev, getUTCNow());
+        adjustTo(periodFromDuration(delta));
     }
 
     public synchronized void setDeltaFromReality(long delta) {
-        DateTime prev = getUTCNow();
-        deltaType = DeltaType.DELTA_ABS;
-        deltaFromRealityDuration = null;
-        deltaFromRealityDurationEpsilon = 0;
-        deltaFromRealityMs = delta;
-        logClockAdjustment(prev, getUTCNow());
+        adjustTo(new Period(delta));
     }
 
     public synchronized void addDeltaFromReality(long delta) {
-        DateTime prev = getUTCNow();
-        if (deltaType != DeltaType.DELTA_ABS) {
-            throw new RuntimeException("ClockMock should be set with type DELTA_ABS");
-        }
-        deltaFromRealityDuration = null;
-        deltaFromRealityDurationEpsilon = 0;
-        deltaFromRealityMs += delta;
-        logClockAdjustment(prev, getUTCNow());
+        adjustTo(new Period(delta));
     }
 
     public synchronized void resetDeltaFromReality() {
-        deltaType = DeltaType.DELTA_NONE;
-        deltaFromRealityDuration = null;
-        deltaFromRealityDurationEpsilon = 0;
-        deltaFromRealityMs = 0;
+        reset();
     }
+    
+    public ReadablePeriod periodFromDuration(Duration duration) {
+        if (duration.getUnit() != TimeUnit.UNLIMITED) {return new Period();}
 
-    private DateTime adjust(DateTime realNow) {
-        switch(deltaType) {
-            case DELTA_NONE:
-                return realNow;
-            case DELTA_ABS:
-                return adjustFromAbsolute(realNow);
-            case DELTA_DURATION:
-                return adjustFromDuration(realNow);
-            default:
-                return null;
-        }
-    }
-
-    private DateTime adjustFromDuration(DateTime input) {
-
-        DateTime result = input;
-        for (Duration cur : deltaFromRealityDuration) {
-            switch (cur.getUnit()) {
+        switch (duration.getUnit()) {
             case DAYS:
-                result = result.plusDays(cur.getNumber());
-                break;
-
+                return Days.days(duration.getNumber());
             case MONTHS:
-                result = result.plusMonths(cur.getNumber());
-                break;
-
+                return Months.months(duration.getNumber());
             case YEARS:
-                result = result.plusYears(cur.getNumber());
-                break;
-
+                return Years.years(duration.getNumber());
             case UNLIMITED:
-            default:
-                throw new RuntimeException("ClockMock is adjusting an unlimited time period");
-            }
+                return Years.years(100);
+           default:
+                return new Period();
         }
-        if (deltaFromRealityDurationEpsilon != 0) {
-            result = result.plus(deltaFromRealityDurationEpsilon);
-        }
-        return result;
-    }
-
-    private DateTime adjustFromAbsolute(DateTime input) {
-        return truncateMs(input.plus(deltaFromRealityMs));
     }
-
-    @Override
-    public String toString() {
-        return getUTCNow().toString();
-    }
-
     
+
 }
diff --git a/util/src/test/java/com/ning/billing/util/clock/MockClockModule.java b/util/src/test/java/com/ning/billing/util/clock/MockClockModule.java
index a8f0605..ece94b0 100644
--- a/util/src/test/java/com/ning/billing/util/clock/MockClockModule.java
+++ b/util/src/test/java/com/ning/billing/util/clock/MockClockModule.java
@@ -28,3 +28,4 @@ public class MockClockModule extends AbstractModule {
 	}
 
 }
+ 
\ No newline at end of file
diff --git a/util/src/test/java/com/ning/billing/util/clock/OldClockMock.java b/util/src/test/java/com/ning/billing/util/clock/OldClockMock.java
new file mode 100644
index 0000000..b31db77
--- /dev/null
+++ b/util/src/test/java/com/ning/billing/util/clock/OldClockMock.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.clock;
+
+import com.ning.billing.catalog.api.Duration;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+// STEPH should really be in tests but not accessible from other sub modules
+public class OldClockMock extends DefaultClock {
+
+    private static final Logger log = LoggerFactory.getLogger(OldClockMock.class);
+
+    private enum DeltaType {
+        DELTA_NONE,
+        DELTA_DURATION,
+        DELTA_ABS
+    }
+
+    private long deltaFromRealityMs;
+    private List<Duration> deltaFromRealityDuration;
+    private long deltaFromRealityDurationEpsilon;
+    private DeltaType deltaType;
+
+    public OldClockMock() {
+        deltaType = DeltaType.DELTA_NONE;
+        deltaFromRealityMs = 0;
+        deltaFromRealityDurationEpsilon = 0;
+        deltaFromRealityDuration = null;
+    }
+
+    @Override
+    public synchronized DateTime getNow(DateTimeZone tz) {
+        return adjust(super.getNow(tz));
+    }
+
+    @Override
+    public synchronized DateTime getUTCNow() {
+        return getNow(DateTimeZone.UTC);
+    }
+
+    private void logClockAdjustment(DateTime prev, DateTime next) {
+        log.info(String.format("            ************      ADJUSTING CLOCK FROM %s to %s     ********************", prev, next));
+    }
+
+    public synchronized void setDeltaFromReality(Duration delta, long epsilon) {
+        DateTime prev = getUTCNow();
+        deltaType = DeltaType.DELTA_DURATION;
+        deltaFromRealityDuration = new ArrayList<Duration>();
+        deltaFromRealityDuration.add(delta);
+        deltaFromRealityDurationEpsilon = epsilon;
+        deltaFromRealityMs = 0;
+        logClockAdjustment(prev, getUTCNow());
+    }
+
+    public synchronized void addDeltaFromReality(Duration delta) {
+        DateTime prev = getUTCNow();
+        if (deltaType != DeltaType.DELTA_DURATION) {
+            throw new RuntimeException("ClockMock should be set with type DELTA_DURATION");
+        }
+        deltaFromRealityDuration.add(delta);
+        logClockAdjustment(prev, getUTCNow());
+    }
+
+    public synchronized void setDeltaFromReality(long delta) {
+        DateTime prev = getUTCNow();
+        deltaType = DeltaType.DELTA_ABS;
+        deltaFromRealityDuration = null;
+        deltaFromRealityDurationEpsilon = 0;
+        deltaFromRealityMs = delta;
+        logClockAdjustment(prev, getUTCNow());
+    }
+
+    public synchronized void addDeltaFromReality(long delta) {
+        DateTime prev = getUTCNow();
+        if (deltaType != DeltaType.DELTA_ABS) {
+            throw new RuntimeException("ClockMock should be set with type DELTA_ABS");
+        }
+        deltaFromRealityDuration = null;
+        deltaFromRealityDurationEpsilon = 0;
+        deltaFromRealityMs += delta;
+        logClockAdjustment(prev, getUTCNow());
+    }
+
+    public synchronized void resetDeltaFromReality() {
+        deltaType = DeltaType.DELTA_NONE;
+        deltaFromRealityDuration = null;
+        deltaFromRealityDurationEpsilon = 0;
+        deltaFromRealityMs = 0;
+    }
+
+    private DateTime adjust(DateTime realNow) {
+        switch(deltaType) {
+            case DELTA_NONE:
+                return realNow;
+            case DELTA_ABS:
+                return adjustFromAbsolute(realNow);
+            case DELTA_DURATION:
+                return adjustFromDuration(realNow);
+            default:
+                return null;
+        }
+    }
+
+    private DateTime adjustFromDuration(DateTime input) {
+
+        DateTime result = input;
+        for (Duration cur : deltaFromRealityDuration) {
+            switch (cur.getUnit()) {
+            case DAYS:
+                result = result.plusDays(cur.getNumber());
+                break;
+
+            case MONTHS:
+                result = result.plusMonths(cur.getNumber());
+                break;
+
+            case YEARS:
+                result = result.plusYears(cur.getNumber());
+                break;
+
+            case UNLIMITED:
+            default:
+                throw new RuntimeException("ClockMock is adjusting an unlimited time period");
+            }
+        }
+        if (deltaFromRealityDurationEpsilon != 0) {
+            result = result.plus(deltaFromRealityDurationEpsilon);
+        }
+        return result;
+    }
+
+    private DateTime adjustFromAbsolute(DateTime input) {
+        return truncateMs(input.plus(deltaFromRealityMs));
+    }
+
+    @Override
+    public String toString() {
+        return getUTCNow().toString();
+    }
+
+    
+}