killbill-aplcache

Changes

junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestOverdueEventCalculator.java 722(+0 -722)

Details

diff --git a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
index efeb07d..6eab3f3 100644
--- a/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
+++ b/account/src/main/java/com/ning/billing/account/api/DefaultAccount.java
@@ -26,6 +26,7 @@ import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.junction.api.BlockingState;
 
 import javax.annotation.Nullable;
 
@@ -279,7 +280,12 @@ public class DefaultAccount extends ExtendedEntityBase implements Account {
 				", postalCode=" + postalCode +
 				", country=" + country +
 				", tags=" + tags +
-                ", fields=" + fields +
-                "]";
+				", fields=" + fields +
+				"]";
+	}
+
+	@Override
+	public BlockingState getBlockingState() {
+	    throw new UnsupportedOperationException();
 	}
 }
\ No newline at end of file
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java b/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java
index 5e94f15..0efe360 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockAccount.java
@@ -25,6 +25,7 @@ import org.joda.time.DateTimeZone;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.MutableAccountData;
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.customfield.CustomField;
 import com.ning.billing.util.tag.Tag;
@@ -249,4 +250,9 @@ public class MockAccount implements Account
         throw new UnsupportedOperationException();
     }
 
+    @Override
+    public BlockingState getBlockingState() {
+        throw new UnsupportedOperationException();
+    }
+
 }
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockEntitlementUserApi.java b/analytics/src/test/java/com/ning/billing/analytics/MockEntitlementUserApi.java
index f9989af..3a2baac 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockEntitlementUserApi.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockEntitlementUserApi.java
@@ -28,6 +28,7 @@ import com.ning.billing.entitlement.api.user.EntitlementUserApi;
 import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.overdue.OverdueState;
 import com.ning.billing.util.callcontext.CallContext;
 
@@ -78,6 +79,11 @@ public class MockEntitlementUserApi implements EntitlementUserApi
             public OverdueState<SubscriptionBundle> getOverdueState() {
                 throw new UnsupportedOperationException();
             }
+
+            @Override
+            public BlockingState getBlockingState() {
+                throw new UnsupportedOperationException();
+            }
         };
     }
 
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
index 7144edb..6767b93 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockSubscription.java
@@ -31,6 +31,7 @@ import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
+import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.customfield.CustomField;
 import com.ning.billing.util.tag.Tag;
@@ -250,4 +251,10 @@ public class MockSubscription implements Subscription
     public List<SubscriptionEventTransition> getBillingTransitions() {
         throw new UnsupportedOperationException();
     }
+
+    @Override
+    public BlockingState getBlockingState() {
+        throw new UnsupportedOperationException();
+    }
+
 }
diff --git a/api/src/main/java/com/ning/billing/account/api/Account.java b/api/src/main/java/com/ning/billing/account/api/Account.java
index 65b97b5..6f2453e 100644
--- a/api/src/main/java/com/ning/billing/account/api/Account.java
+++ b/api/src/main/java/com/ning/billing/account/api/Account.java
@@ -24,5 +24,5 @@ import com.ning.billing.util.tag.Taggable;
 public interface Account extends AccountData, Customizable, UpdatableEntity, Taggable, Blockable{ 
     public static String ObjectType = "account";
     
-    public MutableAccountData toMutableAccountData();    
+    public MutableAccountData toMutableAccountData(); 
 }
diff --git a/api/src/main/java/com/ning/billing/account/api/AccountData.java b/api/src/main/java/com/ning/billing/account/api/AccountData.java
index 654400b..fa78b52 100644
--- a/api/src/main/java/com/ning/billing/account/api/AccountData.java
+++ b/api/src/main/java/com/ning/billing/account/api/AccountData.java
@@ -19,6 +19,7 @@ package com.ning.billing.account.api;
 import org.joda.time.DateTimeZone;
 
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.junction.api.BlockingState;
 
 public interface AccountData {
 
@@ -55,4 +56,5 @@ public interface AccountData {
     public String getCountry();
 
     public String getPhone();
+
 }
diff --git a/api/src/main/java/com/ning/billing/catalog/api/StaticCatalog.java b/api/src/main/java/com/ning/billing/catalog/api/StaticCatalog.java
index d9b0053..17ea132 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/StaticCatalog.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/StaticCatalog.java
@@ -18,10 +18,6 @@ package com.ning.billing.catalog.api;
 
 import java.util.Date;
 
-import com.ning.billing.account.api.Account;
-import com.ning.billing.entitlement.api.user.SubscriptionBundle;
-import com.ning.billing.overdue.config.api.OverdueStateSet;
-
 
 public interface StaticCatalog {
     //
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApiException.java b/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApiException.java
index 693938b..9c35ff0 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApiException.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/EntitlementUserApiException.java
@@ -31,6 +31,10 @@ public class EntitlementUserApiException extends BillingExceptionBase {
         super(e, code, args);
     }
 
+    public EntitlementUserApiException(Throwable e, int code, String message) {
+        super(e, code, message);
+    }
+
     public EntitlementUserApiException(ErrorCode code, Object...args) {
         super(code, args);
     }
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
index b47414b..603ecd9 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
@@ -28,6 +28,7 @@ import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PriceList;
 import com.ning.billing.catalog.api.ProductCategory;
 import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.entity.ExtendedEntity;
 
@@ -76,4 +77,5 @@ public interface Subscription extends ExtendedEntity, Blockable {
     public SubscriptionEventTransition getPreviousTransition();
     
     public List<SubscriptionEventTransition> getBillingTransitions();
+ 
 }
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundle.java b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundle.java
index 717561e..7a5d7b7 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundle.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundle.java
@@ -21,6 +21,7 @@ import java.util.UUID;
 import org.joda.time.DateTime;
 
 import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.overdue.OverdueState;
 
 public interface SubscriptionBundle extends Blockable {
@@ -34,4 +35,5 @@ public interface SubscriptionBundle extends Blockable {
     public String getKey();
 
     public OverdueState<SubscriptionBundle> getOverdueState();
+    
 }
diff --git a/api/src/main/java/com/ning/billing/junction/api/Blockable.java b/api/src/main/java/com/ning/billing/junction/api/Blockable.java
index 6c0976e..39900cc 100644
--- a/api/src/main/java/com/ning/billing/junction/api/Blockable.java
+++ b/api/src/main/java/com/ning/billing/junction/api/Blockable.java
@@ -55,4 +55,6 @@ public interface Blockable {
     }
 
     public UUID getId();
+    
+    public BlockingState getBlockingState();
 }
diff --git a/api/src/main/java/com/ning/billing/junction/api/BlockingApi.java b/api/src/main/java/com/ning/billing/junction/api/BlockingApi.java
index e901d19..18c6799 100644
--- a/api/src/main/java/com/ning/billing/junction/api/BlockingApi.java
+++ b/api/src/main/java/com/ning/billing/junction/api/BlockingApi.java
@@ -32,5 +32,5 @@ public interface BlockingApi {
     public SortedSet<BlockingState> getBlockingHistory(UUID overdueableId, Blockable.Type type);
     
     public <T extends Blockable> void  setBlockingState(BlockingState state);
-
+    
 }
diff --git a/api/src/main/java/com/ning/billing/junction/api/BlockingState.java b/api/src/main/java/com/ning/billing/junction/api/BlockingState.java
index 8c771d2..fcb38fc 100644
--- a/api/src/main/java/com/ning/billing/junction/api/BlockingState.java
+++ b/api/src/main/java/com/ning/billing/junction/api/BlockingState.java
@@ -16,174 +16,25 @@
 
 package com.ning.billing.junction.api;
 
-import java.util.UUID;
-
 import org.joda.time.DateTime;
 
-public class BlockingState implements Comparable<BlockingState>{
-    private final UUID blockingId;
-    private final Blockable.Type type;
-    private final String stateName;
-    private final String service;
-    private final boolean blockChange;
-    private final boolean blockEntitlement;
-    private final boolean blockBilling;
-    private final DateTime timestamp;
-    
-    public BlockingState(UUID blockingId, 
-            String stateName, 
-            Blockable.Type type, 
-            String service,
-            boolean blockChange,
-            boolean blockEntitlement,
-            boolean blockBilling
-            ) {
-        this(   blockingId, 
-                 stateName, 
-                 type, 
-                 service,
-                 blockChange,
-                 blockEntitlement,
-                 blockBilling,
-                 null);
-    }    
-    
-    public BlockingState(UUID blockingId, 
-            String stateName, 
-            Blockable.Type type, 
-            String service,
-            boolean blockChange,
-            boolean blockEntitlement,
-            boolean blockBilling,
-            DateTime timestamp
-            ) {
-        super();
-        this.blockingId = blockingId;
-        this.stateName = stateName;
-        this.service = service;
-        this.blockChange = blockChange;
-        this.blockEntitlement = blockEntitlement;
-        this.blockBilling = blockBilling;
-        this.type = type;
-        this.timestamp = timestamp;
-    }
-    
-    public UUID getBlockedId() {
-        return blockingId;
-    }
-    public String getStateName() {
-        return stateName;
-    }
-    public Blockable.Type getType() {
-        return type;
-    }
-    public DateTime getTimestamp() {
-        return timestamp;
-    }
+public interface BlockingState extends Comparable<BlockingState> {
+
+    public abstract String getStateName();
 
-    public String getService() {
-        return service;
-    }
+    public abstract DateTime getTimestamp();
 
-    public boolean isBlockChange() {
-        return blockChange;
-    }
+    public abstract boolean isBlockChange();
 
-    public boolean isBlockEntitlement() {
-        return blockEntitlement;
-    }
+    public abstract boolean isBlockEntitlement();
 
-    public boolean isBlockBilling() {
-        return blockBilling;
-    }
+    public abstract boolean isBlockBilling();
 
-    @Override
-    public int compareTo(BlockingState arg0) {
-        if (timestamp.compareTo(arg0.getTimestamp()) != 0) {
-            return timestamp.compareTo(arg0.getTimestamp());
-        } else {
-            return hashCode() - arg0.hashCode();
-        }
-    }
+    public abstract int compareTo(BlockingState arg0);
 
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        result = prime * result + (blockBilling ? 1231 : 1237);
-        result = prime * result + (blockChange ? 1231 : 1237);
-        result = prime * result + (blockEntitlement ? 1231 : 1237);
-        result = prime * result + ((blockingId == null) ? 0 : blockingId.hashCode());
-        result = prime * result + ((service == null) ? 0 : service.hashCode());
-        result = prime * result + ((stateName == null) ? 0 : stateName.hashCode());
-        result = prime * result + ((timestamp == null) ? 0 : timestamp.hashCode());
-        result = prime * result + ((type == null) ? 0 : type.hashCode());
-        return result;
-    }
+    public abstract int hashCode();
 
-    @Override
-    public boolean equals(Object obj) {
-        if (this == obj)
-            return true;
-        if (obj == null)
-            return false;
-        if (getClass() != obj.getClass())
-            return false;
-        BlockingState other = (BlockingState) obj;
-        if (blockBilling != other.blockBilling)
-            return false;
-        if (blockChange != other.blockChange)
-            return false;
-        if (blockEntitlement != other.blockEntitlement)
-            return false;
-        if (blockingId == null) {
-            if (other.blockingId != null)
-                return false;
-        } else if (!blockingId.equals(other.blockingId))
-            return false;
-        if (service == null) {
-            if (other.service != null)
-                return false;
-        } else if (!service.equals(other.service))
-            return false;
-        if (stateName == null) {
-            if (other.stateName != null)
-                return false;
-        } else if (!stateName.equals(other.stateName))
-            return false;
-        if (timestamp == null) {
-            if (other.timestamp != null)
-                return false;
-        } else if (!timestamp.equals(other.timestamp))
-            return false;
-        if (type != other.type)
-            return false;
-        return true;
-    }
-    
-    public String getDescription() {
-        String entitlement = onOff(isBlockEntitlement());
-        String billing = onOff(isBlockBilling());
-        String change = onOff(isBlockChange());
-               
-        return String.format("(Change: %s, Entitlement: %s, Billing: %s)", change, entitlement, billing);
-    }
-    
-    private String onOff(boolean val) {
-        if(val) {
-            return "Off";
-        } else {
-            return "On";
-        }
-    }
+    public abstract String getDescription();
 
-    @Override
-    public String toString() {
-        return "BlockingState [blockingId=" + blockingId + ", type=" + type + ", stateName=" + stateName + ", service="
-                + service + ", blockChange=" + blockChange + ", blockEntitlement=" + blockEntitlement
-                + ", blockBilling=" + blockBilling + ", timestamp=" + timestamp + "]";
-    }
-    
-    
-    
-}
+    public abstract String toString();
+}
\ No newline at end of file
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
index d5a0cd9..a6a61b6 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/integration/TestIntegration.java
@@ -27,18 +27,6 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.UUID;
 
-import com.ning.billing.account.api.AccountApiException;
-import com.ning.billing.catalog.api.PhaseType;
-import com.ning.billing.dbi.MysqlTestingHelper;
-import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
-
-import com.ning.billing.invoice.api.Invoice;
-import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.invoice.model.InvoicingConfiguration;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.callcontext.CallOrigin;
-import com.ning.billing.util.callcontext.UserType;
-import com.ning.billing.util.callcontext.DefaultCallContextFactory;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.RandomStringUtils;
 import org.joda.time.DateTime;
@@ -50,10 +38,8 @@ import org.skife.jdbi.v2.TransactionCallback;
 import org.skife.jdbi.v2.TransactionStatus;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
 import org.testng.annotations.AfterMethod;
 import org.testng.annotations.AfterSuite;
-
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.BeforeSuite;
 import org.testng.annotations.Guice;
@@ -61,25 +47,32 @@ import org.testng.annotations.Test;
 
 import com.google.inject.Inject;
 import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.account.api.AccountData;
-import com.ning.billing.account.api.AccountService;
 import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.beatrix.integration.TestBusHandler.NextEvent;
 import com.ning.billing.beatrix.lifecycle.Lifecycle;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.PhaseType;
 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.EntitlementService;
+import com.ning.billing.dbi.MysqlTestingHelper;
 import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
 import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.entitlement.api.user.SubscriptionData;
-import com.ning.billing.invoice.api.InvoiceService;
+import com.ning.billing.invoice.api.Invoice;
+import com.ning.billing.invoice.api.InvoiceItem;
 import com.ning.billing.invoice.api.InvoiceUserApi;
-
-import com.ning.billing.util.clock.ClockMock;
+import com.ning.billing.invoice.model.InvoicingConfiguration;
 import com.ning.billing.util.bus.BusService;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.CallOrigin;
+import com.ning.billing.util.callcontext.DefaultCallContextFactory;
+import com.ning.billing.util.callcontext.UserType;
+import com.ning.billing.util.clock.ClockMock;
 
 @Test(groups = "slow")
 @Guice(modules = {MockModule.class})
@@ -130,6 +123,7 @@ public class TestIntegration {
         final String invoiceDdl = IOUtils.toString(TestIntegration.class.getResourceAsStream("/com/ning/billing/invoice/ddl.sql"));
         final String paymentDdl = IOUtils.toString(TestIntegration.class.getResourceAsStream("/com/ning/billing/payment/ddl.sql"));
         final String utilDdl = IOUtils.toString(TestIntegration.class.getResourceAsStream("/com/ning/billing/util/ddl.sql"));
+        final String blockingDdl = IOUtils.toString(TestIntegration.class.getResourceAsStream("/com/ning/billing/junction/ddl.sql"));
 
         helper.startMysql();
 
@@ -138,6 +132,7 @@ public class TestIntegration {
         helper.initDb(invoiceDdl);
         helper.initDb(paymentDdl);
         helper.initDb(utilDdl);
+        helper.initDb(blockingDdl);
     }
 
     @BeforeSuite(groups = "slow")
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java
index d7b600d..5c7b848 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionBundleData.java
@@ -20,6 +20,7 @@ import java.util.UUID;
 
 import org.joda.time.DateTime;
 
+import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.overdue.OverdueState;
 
 public class SubscriptionBundleData implements SubscriptionBundle {
@@ -69,4 +70,9 @@ public class SubscriptionBundleData implements SubscriptionBundle {
     public OverdueState<SubscriptionBundle> getOverdueState() {
         return overdueState;
     }
+
+    @Override
+    public BlockingState getBlockingState() {
+        throw new UnsupportedOperationException();
+    }
 }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
index feae851..4ccbf95 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionData.java
@@ -37,8 +37,8 @@ import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PriceList;
 import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
 import com.ning.billing.entitlement.api.user.SubscriptionEventTransition.SubscriptionTransitionType;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
 import com.ning.billing.entitlement.api.user.SubscriptionTransitionDataIterator.Kind;
 import com.ning.billing.entitlement.api.user.SubscriptionTransitionDataIterator.Order;
 import com.ning.billing.entitlement.api.user.SubscriptionTransitionDataIterator.TimeLimit;
@@ -48,6 +48,7 @@ import com.ning.billing.entitlement.events.phase.PhaseEvent;
 import com.ning.billing.entitlement.events.user.ApiEvent;
 import com.ning.billing.entitlement.events.user.ApiEventType;
 import com.ning.billing.entitlement.exceptions.EntitlementError;
+import com.ning.billing.junction.api.BlockingState;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.customfield.CustomField;
@@ -448,4 +449,9 @@ public class SubscriptionData extends ExtendedEntityBase implements Subscription
         }
     }
 
+    @Override
+    public BlockingState getBlockingState() {
+        throw new UnsupportedOperationException();
+    }
+
 }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java b/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
index a804bff..c82994c 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/notification/TestNextBillingDateNotifier.java
@@ -63,6 +63,7 @@ import com.ning.billing.junction.plumbing.billing.DefaultBillingApi;
 import com.ning.billing.lifecycle.KillbillService.ServiceException;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.mock.glue.MockJunctionModule;
 import com.ning.billing.util.bus.Bus;
 import com.ning.billing.util.bus.InMemoryBus;
 import com.ning.billing.util.callcontext.CallContextFactory;
@@ -141,10 +142,9 @@ public class TestNextBillingDateNotifier {
                 bind(InvoiceGenerator.class).to(DefaultInvoiceGenerator.class).asEagerSingleton();
                 bind(InvoiceDao.class).to(DefaultInvoiceDao.class);
                 bind(NextBillingDatePoster.class).to(DefaultNextBillingDatePoster.class).asEagerSingleton();
-                bind(AccountUserApi.class).to(MockAccountUserApi.class).asEagerSingleton();
-                bind(BillingApi.class).to(DefaultBillingApi.class).asEagerSingleton();
                 bind(EntitlementUserApi.class).to(DefaultEntitlementUserApi.class).asEagerSingleton();
                 bind(ChargeThruApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(ChargeThruApi.class));
+                install(new MockJunctionModule());
             }
         });
 
diff --git a/junction/src/main/java/com/ning/billing/junction/api/blocking/DefaultBlockingApi.java b/junction/src/main/java/com/ning/billing/junction/api/blocking/DefaultBlockingApi.java
index 02b3b41..27abad0 100644
--- a/junction/src/main/java/com/ning/billing/junction/api/blocking/DefaultBlockingApi.java
+++ b/junction/src/main/java/com/ning/billing/junction/api/blocking/DefaultBlockingApi.java
@@ -39,7 +39,12 @@ public class DefaultBlockingApi implements BlockingApi {
     
     @Override
     public BlockingState getBlockingStateFor(Blockable overdueable) {
-        return dao.getBlockingStateFor(overdueable);
+        BlockingState state = dao.getBlockingStateFor(overdueable);
+        if(state == null) {
+            state = DefaultBlockingState.getClearState();
+        }
+        return state;
+        
     }
 
     @Override
diff --git a/junction/src/main/java/com/ning/billing/junction/api/blocking/DefaultBlockingState.java b/junction/src/main/java/com/ning/billing/junction/api/blocking/DefaultBlockingState.java
new file mode 100644
index 0000000..e7eafd0
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/api/blocking/DefaultBlockingState.java
@@ -0,0 +1,231 @@
+/*
+ * 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.junction.api.blocking;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingState;
+
+public class DefaultBlockingState implements BlockingState{
+
+    private static final String CLEAR_STATE = "clear";
+
+    private static BlockingState clearState= null;
+    
+    private final UUID blockingId;
+    private final Blockable.Type type;
+    private final String stateName;
+    private final String service;
+    private final boolean blockChange;
+    private final boolean blockEntitlement;
+    private final boolean blockBilling;
+    private final DateTime timestamp;
+    
+    public static BlockingState getClearState() {
+        if(clearState == null) {
+            clearState = new DefaultBlockingState(null, CLEAR_STATE, null, null, false, false, false);
+        }
+        return clearState;
+    }    
+    
+    public DefaultBlockingState(UUID blockingId, 
+            String stateName, 
+            Blockable.Type type, 
+            String service,
+            boolean blockChange,
+            boolean blockEntitlement,
+            boolean blockBilling
+            ) {
+        this(   blockingId, 
+                 stateName, 
+                 type, 
+                 service,
+                 blockChange,
+                 blockEntitlement,
+                 blockBilling,
+                 null);
+    }    
+    
+    public DefaultBlockingState(UUID blockingId, 
+            String stateName, 
+            Blockable.Type type, 
+            String service,
+            boolean blockChange,
+            boolean blockEntitlement,
+            boolean blockBilling,
+            DateTime timestamp
+            ) {
+        super();
+        this.blockingId = blockingId;
+        this.stateName = stateName;
+        this.service = service;
+        this.blockChange = blockChange;
+        this.blockEntitlement = blockEntitlement;
+        this.blockBilling = blockBilling;
+        this.type = type;
+        this.timestamp = timestamp;
+    }
+    
+    public UUID getBlockedId() {
+        return blockingId;
+    }
+    /* (non-Javadoc)
+     * @see com.ning.billing.junction.api.blocking.BlockingState#getStateName()
+     */
+    @Override
+    public String getStateName() {
+        return stateName;
+    }
+
+    public Blockable.Type getType() {
+        return type;
+    }
+    /* (non-Javadoc)
+     * @see com.ning.billing.junction.api.blocking.BlockingState#getTimestamp()
+     */
+    @Override
+    public DateTime getTimestamp() {
+        return timestamp;
+    }
+
+    public String getService() {
+        return service;
+    }
+
+    /* (non-Javadoc)
+     * @see com.ning.billing.junction.api.blocking.BlockingState#isBlockChange()
+     */
+    @Override
+    public boolean isBlockChange() {
+        return blockChange;
+    }
+
+    /* (non-Javadoc)
+     * @see com.ning.billing.junction.api.blocking.BlockingState#isBlockEntitlement()
+     */
+    @Override
+    public boolean isBlockEntitlement() {
+        return blockEntitlement;
+    }
+
+    /* (non-Javadoc)
+     * @see com.ning.billing.junction.api.blocking.BlockingState#isBlockBilling()
+     */
+    @Override
+    public boolean isBlockBilling() {
+        return blockBilling;
+    }
+
+    /* (non-Javadoc)
+     * @see com.ning.billing.junction.api.blocking.BlockingState#compareTo(com.ning.billing.junction.api.blocking.DefaultBlockingState)
+     */
+    public int compareTo(BlockingState arg0) {
+        if (timestamp.compareTo(arg0.getTimestamp()) != 0) {
+            return timestamp.compareTo(arg0.getTimestamp());
+        } else {
+            return hashCode() - arg0.hashCode();
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + (blockBilling ? 1231 : 1237);
+        result = prime * result + (blockChange ? 1231 : 1237);
+        result = prime * result + (blockEntitlement ? 1231 : 1237);
+        result = prime * result + ((blockingId == null) ? 0 : blockingId.hashCode());
+        result = prime * result + ((service == null) ? 0 : service.hashCode());
+        result = prime * result + ((stateName == null) ? 0 : stateName.hashCode());
+        result = prime * result + ((timestamp == null) ? 0 : timestamp.hashCode());
+        result = prime * result + ((type == null) ? 0 : type.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        DefaultBlockingState other = (DefaultBlockingState) obj;
+        if (blockBilling != other.blockBilling)
+            return false;
+        if (blockChange != other.blockChange)
+            return false;
+        if (blockEntitlement != other.blockEntitlement)
+            return false;
+        if (blockingId == null) {
+            if (other.blockingId != null)
+                return false;
+        } else if (!blockingId.equals(other.blockingId))
+            return false;
+        if (service == null) {
+            if (other.service != null)
+                return false;
+        } else if (!service.equals(other.service))
+            return false;
+        if (stateName == null) {
+            if (other.stateName != null)
+                return false;
+        } else if (!stateName.equals(other.stateName))
+            return false;
+        if (timestamp == null) {
+            if (other.timestamp != null)
+                return false;
+        } else if (!timestamp.equals(other.timestamp))
+            return false;
+        if (type != other.type)
+            return false;
+        return true;
+    }
+    
+    /* (non-Javadoc)
+     * @see com.ning.billing.junction.api.blocking.BlockingState#getDescription()
+     */
+    @Override
+    public String getDescription() {
+        String entitlement = onOff(isBlockEntitlement());
+        String billing = onOff(isBlockBilling());
+        String change = onOff(isBlockChange());
+               
+        return String.format("(Change: %s, Entitlement: %s, Billing: %s)", change, entitlement, billing);
+    }
+    
+    private String onOff(boolean val) {
+        if(val) {
+            return "Off";
+        } else {
+            return "On";
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "BlockingState [blockingId=" + blockingId + ", type=" + type + ", stateName=" + stateName + ", service="
+                + service + ", blockChange=" + blockChange + ", blockEntitlement=" + blockEntitlement
+                + ", blockBilling=" + blockBilling + ", timestamp=" + timestamp + "]";
+    }
+
+
+    
+}
diff --git a/junction/src/main/java/com/ning/billing/junction/block/BlockingChecker.java b/junction/src/main/java/com/ning/billing/junction/block/BlockingChecker.java
index a6ab7da..04d68f0 100644
--- a/junction/src/main/java/com/ning/billing/junction/block/BlockingChecker.java
+++ b/junction/src/main/java/com/ning/billing/junction/block/BlockingChecker.java
@@ -16,29 +16,22 @@
 
 package com.ning.billing.junction.block;
 
-import com.ning.billing.account.api.Account;
-import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import java.util.UUID;
+
+import com.ning.billing.junction.api.Blockable;
 import com.ning.billing.junction.api.BlockingApiException;
 
 public interface BlockingChecker {
 
-    public void checkBlockedChange(Subscription subscription)  throws BlockingApiException;
-
-    public void checkBlockedChange(SubscriptionBundle bundle) throws BlockingApiException;
-
-    public void checkBlockedChange(Account account) throws BlockingApiException;
-
-    public void checkBlockedEntitlement(Subscription subscription)  throws BlockingApiException;
-
-    public void checkBlockedEntitlement(SubscriptionBundle bundle) throws BlockingApiException;
+    public void checkBlockedChange(Blockable blockable)  throws BlockingApiException;
 
-    public void checkBlockedEntitlement(Account account) throws BlockingApiException;
+    public void checkBlockedEntitlement(Blockable blockable)  throws BlockingApiException;
 
-    public void checkBlockedBilling(Subscription subscription)  throws BlockingApiException;
+    public void checkBlockedBilling(Blockable blockable)  throws BlockingApiException;
 
-    public void checkBlockedBilling(SubscriptionBundle bundleId) throws BlockingApiException;
+    public void checkBlockedChange(UUID bundleId, Blockable.Type type) throws BlockingApiException;
 
-    public void checkBlockedBilling(Account account) throws BlockingApiException;
+    public void checkBlockedEntitlement(UUID bundleId, Blockable.Type type) throws BlockingApiException;
 
+    public void checkBlockedBilling(UUID bundleId, Blockable.Type type) throws BlockingApiException;
 }
diff --git a/junction/src/main/java/com/ning/billing/junction/block/DefaultBlockingChecker.java b/junction/src/main/java/com/ning/billing/junction/block/DefaultBlockingChecker.java
index 1f65391..838a457 100644
--- a/junction/src/main/java/com/ning/billing/junction/block/DefaultBlockingChecker.java
+++ b/junction/src/main/java/com/ning/billing/junction/block/DefaultBlockingChecker.java
@@ -72,7 +72,7 @@ public class DefaultBlockingChecker implements BlockingChecker {
 
     private final EntitlementUserApi entitlementApi;
     private final BlockingStateDao dao;
-
+    
     @Inject
     public DefaultBlockingChecker(EntitlementUserApi entitlementApi, BlockingStateDao dao) {
         this.entitlementApi = entitlementApi;
@@ -87,12 +87,11 @@ public class DefaultBlockingChecker implements BlockingChecker {
     public BlockingAggregator getBlockedStateSubscription(Subscription subscription)  {
         BlockingAggregator result = new BlockingAggregator();
         if(subscription != null) {
-            BlockingState subscriptionState = dao.getBlockingStateFor(subscription);
+            BlockingState subscriptionState = subscription.getBlockingState();
             if(subscriptionState != null) {
                 result.or(subscriptionState);
             }
             if(subscription.getBundleId() != null) {
-                SubscriptionBundle bundle = entitlementApi.getBundleFromId(subscription.getBundleId());
                 result.or(getBlockedStateBundleId(subscription.getBundleId()));
             } 
         }
@@ -105,15 +104,15 @@ public class DefaultBlockingChecker implements BlockingChecker {
      }
      
     public BlockingAggregator getBlockedStateBundle(SubscriptionBundle bundle)  {
-        BlockingAggregator result = getBlockedStateAccount(bundle.getAccountId());
-        BlockingState bundleState = dao.getBlockingStateFor(bundle);
+        BlockingAggregator result = getBlockedStateAccountId(bundle.getAccountId());
+        BlockingState bundleState = bundle.getBlockingState();
         if(bundleState != null) {
             result.or(bundleState);
         }
         return result;
     }
 
-    public BlockingAggregator getBlockedStateAccount(UUID accountId)  {
+    public BlockingAggregator getBlockedStateAccountId(UUID accountId)  {
         BlockingAggregator result = new BlockingAggregator();
         if(accountId != null) {
             BlockingState accountState = dao.getBlockingStateFor(accountId, Blockable.Type.ACCOUNT);
@@ -124,72 +123,77 @@ public class DefaultBlockingChecker implements BlockingChecker {
 
     public BlockingAggregator getBlockedStateAccount(Account account)  {
         if(account != null) {
-            return getBlockedStateAccount(account.getId());
+            return getBlockedStateAccountId(account.getId());
         }
         return new BlockingAggregator();
     }
     @Override
-    public void checkBlockedChange(Subscription subscription) throws BlockingApiException {
-        if(getBlockedStateSubscription(subscription).isBlockChange()) {
-            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_SUBSCRIPTION, subscription.getId().toString());
-        }
-    }
-
-    @Override
-    public void checkBlockedChange(SubscriptionBundle bundle) throws BlockingApiException {
-        if(getBlockedStateBundle(bundle).isBlockChange()) {
-            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_BUNDLE, bundle.getId().toString());
+    public void checkBlockedChange(Blockable blockable) throws BlockingApiException  {
+        if(blockable instanceof Subscription && getBlockedStateSubscription((Subscription) blockable).isBlockChange()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_SUBSCRIPTION, blockable.getId().toString());
+        } else if(blockable instanceof SubscriptionBundle &&  getBlockedStateBundle((SubscriptionBundle) blockable).isBlockChange()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_BUNDLE, blockable.getId().toString());
+        } else if(blockable instanceof Account && getBlockedStateAccount((Account) blockable).isBlockChange()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_ACCOUNT, blockable.getId().toString());
         }
     }
 
     @Override
-    public void checkBlockedChange(Account account) throws BlockingApiException {
-        if(getBlockedStateAccount(account).isBlockChange()) {
-            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_ACCOUNT, account.getId().toString());
+    public void checkBlockedEntitlement(Blockable blockable) throws BlockingApiException  {
+        if(blockable instanceof Subscription && getBlockedStateSubscription((Subscription) blockable).isBlockEntitlement()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_SUBSCRIPTION, blockable.getId().toString());
+        } else if(blockable instanceof SubscriptionBundle &&  getBlockedStateBundle((SubscriptionBundle) blockable).isBlockEntitlement()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_BUNDLE, blockable.getId().toString());
+        } else if(blockable instanceof Account && getBlockedStateAccount((Account) blockable).isBlockEntitlement()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_ACCOUNT, blockable.getId().toString());
         }
     }
 
     @Override
-    public void checkBlockedEntitlement(Subscription subscription) throws BlockingApiException {
-        if(getBlockedStateSubscription(subscription).isBlockEntitlement()) {
-            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_SUBSCRIPTION, subscription.getId().toString());
+    public void checkBlockedBilling(Blockable blockable) throws BlockingApiException  {
+        if(blockable instanceof Subscription && getBlockedStateSubscription((Subscription) blockable).isBlockBilling()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_SUBSCRIPTION, blockable.getId().toString());
+        } else if(blockable instanceof SubscriptionBundle &&  getBlockedStateBundle((SubscriptionBundle) blockable).isBlockBilling()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_BUNDLE, blockable.getId().toString());
+        } else if(blockable instanceof Account && getBlockedStateAccount((Account) blockable).isBlockBilling()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_ACCOUNT, blockable.getId().toString());
         }
     }
 
     @Override
-    public void checkBlockedEntitlement(SubscriptionBundle bundle) throws BlockingApiException {
-        if(getBlockedStateBundle(bundle).isBlockEntitlement()) {
-            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_BUNDLE, bundle.getId().toString());
+    public void checkBlockedChange(UUID blockableId, Blockable.Type type) throws BlockingApiException  {
+        if(type == Blockable.Type.SUBSCRIPTION && getBlockedStateSubscriptionId(blockableId).isBlockChange()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_SUBSCRIPTION, blockableId.toString());
+        } else if(type == Blockable.Type.SUBSCRIPTION_BUNDLE  &&  getBlockedStateBundleId(blockableId).isBlockChange()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_BUNDLE, blockableId.toString());
+        } else if(type == Blockable.Type.ACCOUNT  && getBlockedStateAccountId(blockableId).isBlockChange()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_CHANGE, TYPE_ACCOUNT, blockableId.toString());
         }
     }
 
     @Override
-    public void checkBlockedEntitlement(Account account) throws BlockingApiException {
-        if(getBlockedStateAccount(account).isBlockEntitlement()) {
-            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_ACCOUNT, account.getId().toString());
+    public void checkBlockedEntitlement(UUID blockableId, Blockable.Type type) throws BlockingApiException  {
+        if(type == Blockable.Type.SUBSCRIPTION && getBlockedStateSubscriptionId(blockableId).isBlockEntitlement()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_SUBSCRIPTION, blockableId.toString());
+        } else if(type == Blockable.Type.SUBSCRIPTION_BUNDLE  &&  getBlockedStateBundleId(blockableId).isBlockEntitlement()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_BUNDLE, blockableId.toString());
+        } else if(type == Blockable.Type.ACCOUNT  && getBlockedStateAccountId(blockableId).isBlockEntitlement()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_ENTITLEMENT, TYPE_ACCOUNT, blockableId.toString());
         }
     }
 
     @Override
-    public void checkBlockedBilling(Subscription subscription) throws BlockingApiException {
-        if(getBlockedStateSubscription(subscription).isBlockBilling()) {
-            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_SUBSCRIPTION, subscription.getId().toString());
+    public void checkBlockedBilling(UUID blockableId, Blockable.Type type) throws BlockingApiException  {
+        if(type == Blockable.Type.SUBSCRIPTION && getBlockedStateSubscriptionId(blockableId).isBlockBilling()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_SUBSCRIPTION, blockableId.toString());
+        } else if(type == Blockable.Type.SUBSCRIPTION_BUNDLE  &&  getBlockedStateBundleId(blockableId).isBlockBilling()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_BUNDLE, blockableId.toString());
+        } else if(type == Blockable.Type.ACCOUNT  && getBlockedStateAccountId(blockableId).isBlockBilling()) {
+            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_ACCOUNT, blockableId.toString());
         }
     }
 
-    @Override
-    public void checkBlockedBilling(SubscriptionBundle bundle) throws BlockingApiException {
-        if(getBlockedStateBundle(bundle).isBlockBilling()) {
-            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_BUNDLE, bundle.getId().toString());
-        }
-    }
 
-    @Override
-    public void checkBlockedBilling(Account account) throws BlockingApiException {
-        if(getBlockedStateAccount(account).isBlockBilling()) {
-            throw new BlockingApiException(ErrorCode.BLOCK_BLOCKED_ACTION,ACTION_BILLING, TYPE_ACCOUNT, account.getId().toString());
-        }
-    }
 
     
 }
diff --git a/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateSqlDao.java b/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateSqlDao.java
index 895724c..22e3d07 100644
--- a/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateSqlDao.java
+++ b/junction/src/main/java/com/ning/billing/junction/dao/BlockingStateSqlDao.java
@@ -39,6 +39,7 @@ import com.ning.billing.junction.api.Blockable.Type;
 import com.ning.billing.junction.api.BlockingApi;
 import com.ning.billing.junction.api.BlockingApiException;
 import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.junction.api.blocking.DefaultBlockingState;
 import com.ning.billing.overdue.OverdueState;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.dao.BinderBase;
@@ -101,7 +102,7 @@ public interface BlockingStateSqlDao extends BlockingStateDao, CloseMe, Transmog
             } catch (BlockingApiException e) {
                 throw new SQLException(e);
             }
-            return new BlockingState(blockableId, stateName, type, service, blockChange, blockEntitlement, blockBilling, timestamp);
+            return new DefaultBlockingState(blockableId, stateName, type, service, blockChange, blockEntitlement, blockBilling, timestamp);
         }    
     }
     
@@ -114,9 +115,9 @@ public interface BlockingStateSqlDao extends BlockingStateDao, CloseMe, Transmog
         }
     }
     
-    public static class BlockingStateBinder extends BinderBase implements Binder<Bind, BlockingState> {
+    public static class BlockingStateBinder extends BinderBase implements Binder<Bind, DefaultBlockingState> {
         @Override
-        public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, BlockingState state) {
+        public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, DefaultBlockingState state) {
             stmt.bind("id", state.getBlockedId().toString()); 
             stmt.bind("state", state.getStateName().toString());
             stmt.bind("type", state.getType().toString());
diff --git a/junction/src/main/java/com/ning/billing/junction/glue/JunctionModule.java b/junction/src/main/java/com/ning/billing/junction/glue/JunctionModule.java
index 80cfe58..1c87dfe 100644
--- a/junction/src/main/java/com/ning/billing/junction/glue/JunctionModule.java
+++ b/junction/src/main/java/com/ning/billing/junction/glue/JunctionModule.java
@@ -28,17 +28,22 @@ import com.ning.billing.junction.api.blocking.DefaultBlockingApi;
 import com.ning.billing.junction.dao.BlockingStateDao;
 import com.ning.billing.junction.dao.BlockingStateSqlDao;
 import com.ning.billing.junction.plumbing.api.BlockingAccountUserApi;
+import com.ning.billing.junction.plumbing.billing.BlockingCalculator;
 import com.ning.billing.junction.plumbing.billing.DefaultBillingApi;
 
 public class JunctionModule extends AbstractModule {
 
     @Override
     protected void configure() {
+        // External
         installBlockingApi();
         installAccountUserApi();
-        installBlockingStateDao();
         installBillingApi();
-    }
+        
+        // Internal
+        installBlockingCalculator();
+        installBlockingStateDao();
+     }
 
     protected void installBillingApi() {
         bind(BillingApi.class).to(DefaultBillingApi.class).asEagerSingleton();
@@ -56,6 +61,10 @@ public class JunctionModule extends AbstractModule {
         bind(BlockingApi.class).to(DefaultBlockingApi.class).asEagerSingleton();
     }
     
+    protected void installBlockingCalculator() {
+        bind(BlockingCalculator.class).asEagerSingleton();
+    }
+
     public static class BlockingDaoProvider implements Provider<BlockingStateDao>{        
         private IDBI dbi;
 
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccount.java b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccount.java
new file mode 100644
index 0000000..b438d62
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccount.java
@@ -0,0 +1,212 @@
+/*
+ * 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.junction.plumbing.api;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.MutableAccountData;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.customfield.CustomField;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.TagDefinition;
+
+public class BlockingAccount implements Account {
+    private final Account account;
+    private BlockingState blockingState = null;
+    private BlockingApi blockingApi;
+
+    public BlockingAccount(Account account, BlockingApi blockingApi) {
+        this.account = account;
+        this.blockingApi = blockingApi;
+    }
+
+    public List<Tag> getTagList() {
+        return account.getTagList();
+    }
+
+    public String getUpdatedBy() {
+        return account.getUpdatedBy();
+    }
+
+    public UUID getId() {
+        return account.getId();
+    }
+
+    public String getCreatedBy() {
+        return account.getCreatedBy();
+    }
+
+    public boolean hasTag(String tagName) {
+        return account.hasTag(tagName);
+    }
+
+    public DateTime getUpdatedDate() {
+        return account.getUpdatedDate();
+    }
+
+    public DateTime getCreatedDate() {
+        return account.getCreatedDate();
+    }
+
+    public void addTag(TagDefinition definition) {
+        account.addTag(definition);
+    }
+
+    public String getFieldValue(String fieldName) {
+        return account.getFieldValue(fieldName);
+    }
+
+    public String getExternalKey() {
+        return account.getExternalKey();
+    }
+
+    public String getName() {
+        return account.getName();
+    }
+
+    public void addTags(List<Tag> tags) {
+        account.addTags(tags);
+    }
+
+    public void setFieldValue(String fieldName, String fieldValue) {
+        account.setFieldValue(fieldName, fieldValue);
+    }
+
+    public int getFirstNameLength() {
+        return account.getFirstNameLength();
+    }
+
+    public void clearTags() {
+        account.clearTags();
+    }
+
+    public String getEmail() {
+        return account.getEmail();
+    }
+
+    public void removeTag(TagDefinition definition) {
+        account.removeTag(definition);
+    }
+
+    public void saveFieldValue(String fieldName, String fieldValue, CallContext context) {
+        account.saveFieldValue(fieldName, fieldValue, context);
+    }
+
+    public int getBillCycleDay() {
+        return account.getBillCycleDay();
+    }
+
+    public boolean generateInvoice() {
+        return account.generateInvoice();
+    }
+
+    public Currency getCurrency() {
+        return account.getCurrency();
+    }
+
+    public boolean processPayment() {
+        return account.processPayment();
+    }
+
+    public List<CustomField> getFieldList() {
+        return account.getFieldList();
+    }
+
+    public String getPaymentProviderName() {
+        return account.getPaymentProviderName();
+    }
+
+    public MutableAccountData toMutableAccountData() {
+        return account.toMutableAccountData();
+    }
+
+    public void setFields(List<CustomField> fields) {
+        account.setFields(fields);
+    }
+
+    public DateTimeZone getTimeZone() {
+        return account.getTimeZone();
+    }
+
+    public String getLocale() {
+        return account.getLocale();
+    }
+
+    public BlockingState getBlockingState() {
+        if(blockingState == null) {
+            blockingState = blockingApi.getBlockingStateFor(account);
+        }
+        return blockingState;
+    }
+
+    public void saveFields(List<CustomField> fields, CallContext context) {
+        account.saveFields(fields, context);
+    }
+
+    public String getAddress1() {
+        return account.getAddress1();
+    }
+
+    public String getAddress2() {
+        return account.getAddress2();
+    }
+
+    public void clearFields() {
+        account.clearFields();
+    }
+
+    public String getCompanyName() {
+        return account.getCompanyName();
+    }
+
+    public void clearPersistedFields(CallContext context) {
+        account.clearPersistedFields(context);
+    }
+
+    public String getCity() {
+        return account.getCity();
+    }
+
+    public String getStateOrProvince() {
+        return account.getStateOrProvince();
+    }
+
+    public String getObjectName() {
+        return account.getObjectName();
+    }
+
+    public String getPostalCode() {
+        return account.getPostalCode();
+    }
+
+    public String getCountry() {
+        return account.getCountry();
+    }
+
+    public String getPhone() {
+        return account.getPhone();
+    }
+
+}
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccountUserApi.java b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccountUserApi.java
index 2fc3110..6e67325 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccountUserApi.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingAccountUserApi.java
@@ -25,18 +25,20 @@ import com.ning.billing.account.api.AccountApiException;
 import com.ning.billing.account.api.AccountData;
 import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.account.api.MigrationAccountData;
+import com.ning.billing.junction.api.BlockingApi;
 import com.ning.billing.util.callcontext.CallContext;
 import com.ning.billing.util.customfield.CustomField;
 import com.ning.billing.util.glue.RealImplementation;
 import com.ning.billing.util.tag.Tag;
 
-public class BlockingAccountUserApi implements AccountUserApi {
-    
+public class BlockingAccountUserApi implements AccountUserApi { 
     private AccountUserApi userApi;
+    private BlockingApi blockingApi;
 
     @Inject
-    public BlockingAccountUserApi(@RealImplementation AccountUserApi userApi) {
+    public BlockingAccountUserApi(@RealImplementation AccountUserApi userApi, BlockingApi blockingApi) {
         this.userApi = userApi;
+        this.blockingApi = blockingApi;
     }
 
     @Override
@@ -68,7 +70,7 @@ public class BlockingAccountUserApi implements AccountUserApi {
 
     @Override
     public Account getAccountByKey(String key) {
-        return userApi.getAccountByKey(key);
+        return new BlockingAccount(userApi.getAccountByKey(key), blockingApi);
     }
 
     @Override
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingEntitlementUserApi.java b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingEntitlementUserApi.java
new file mode 100644
index 0000000..14eba4b
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingEntitlementUserApi.java
@@ -0,0 +1,117 @@
+/*
+ * 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.junction.plumbing.api;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.google.inject.Inject;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.entitlement.api.user.EntitlementUserApi;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.api.BlockingApiException;
+import com.ning.billing.junction.block.BlockingChecker;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.glue.RealImplementation;
+
+public class BlockingEntitlementUserApi implements EntitlementUserApi {
+    private final EntitlementUserApi entitlementUserApi;
+    private final BlockingApi blockingApi;
+    private final BlockingChecker checker;
+    
+    @Inject
+    public BlockingEntitlementUserApi(@RealImplementation EntitlementUserApi userApi, BlockingApi blockingApi, BlockingChecker checker) {
+        this.entitlementUserApi = userApi;
+        this.blockingApi = blockingApi;
+        this.checker = checker;
+    }
+
+    public SubscriptionBundle getBundleFromId(UUID id) {
+        return new BlockingSubscriptionBundle(entitlementUserApi.getBundleFromId(id), blockingApi);
+    }
+
+    public Subscription getSubscriptionFromId(UUID id) {
+        return new BlockingSubscription(entitlementUserApi.getSubscriptionFromId(id), blockingApi, checker);
+    }
+
+    public SubscriptionBundle getBundleForKey(String bundleKey) {
+        return new BlockingSubscriptionBundle(entitlementUserApi.getBundleForKey(bundleKey), blockingApi);
+    }
+
+    public List<SubscriptionBundle> getBundlesForAccount(UUID accountId) {
+        List<SubscriptionBundle> result = new ArrayList<SubscriptionBundle>();
+        List<SubscriptionBundle> bundles = entitlementUserApi.getBundlesForAccount(accountId);
+        for(SubscriptionBundle bundle : bundles) {
+            result.add(new BlockingSubscriptionBundle(bundle, blockingApi));
+        }
+        return result;
+    }
+
+    public List<Subscription> getSubscriptionsForBundle(UUID bundleId) {
+        List<Subscription> result = new ArrayList<Subscription>();
+        List<Subscription> subscriptions = entitlementUserApi.getSubscriptionsForBundle(bundleId);
+        for(Subscription subscription : subscriptions) {
+            result.add(new BlockingSubscription(subscription, blockingApi, checker));
+        }
+        return result;
+    }
+
+    public List<Subscription> getSubscriptionsForKey(String bundleKey) {
+        List<Subscription> result = new ArrayList<Subscription>();
+        List<Subscription> subscriptions = entitlementUserApi.getSubscriptionsForKey(bundleKey);
+        for(Subscription subscription : subscriptions) {
+            result.add(new BlockingSubscription(subscription, blockingApi, checker));
+        }
+        return result;
+    }
+
+    public Subscription getBaseSubscription(UUID bundleId) {
+        return new BlockingSubscription(entitlementUserApi.getBaseSubscription(bundleId), blockingApi, checker);
+    }
+
+    public SubscriptionBundle createBundleForAccount(UUID accountId, String bundleKey, CallContext context)
+            throws EntitlementUserApiException {
+        try {
+            checker.checkBlockedChange(accountId, Blockable.Type.ACCOUNT);
+            return new BlockingSubscriptionBundle(entitlementUserApi.createBundleForAccount(accountId, bundleKey, context), blockingApi);
+        }catch (BlockingApiException e) {
+            throw new EntitlementUserApiException(e, e.getCode(), e.getMessage());
+        }
+   }
+
+    public Subscription createSubscription(UUID bundleId, PlanPhaseSpecifier spec, DateTime requestedDate,
+            CallContext context) throws EntitlementUserApiException {
+        try {
+            checker.checkBlockedChange(bundleId, Blockable.Type.SUBSCRIPTION_BUNDLE);
+            return new BlockingSubscription(createSubscription(bundleId, spec, requestedDate, context), blockingApi, checker);
+        }catch (BlockingApiException e) {
+            throw new EntitlementUserApiException(e, e.getCode(), e.getMessage());
+        }
+    }
+
+    public DateTime getNextBillingDate(UUID account) {
+        return entitlementUserApi.getNextBillingDate(account);
+    }
+
+}
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingSubscription.java b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingSubscription.java
new file mode 100644
index 0000000..32705f6
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingSubscription.java
@@ -0,0 +1,218 @@
+/*
+ * 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.junction.plumbing.api;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.PriceList;
+import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.entitlement.api.user.EntitlementUserApiException;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionEventTransition;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.api.BlockingApiException;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.junction.block.BlockingChecker;
+import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.customfield.CustomField;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.TagDefinition;
+
+
+public class BlockingSubscription implements Subscription {
+    private final Subscription subscription;
+    private final BlockingApi blockingApi; 
+    private final BlockingChecker checker;
+    
+    private BlockingState blockingState = null;
+
+    public BlockingSubscription(Subscription subscription, BlockingApi blockingApi, BlockingChecker checker) {
+        this.subscription = subscription;
+        this.blockingApi = blockingApi;
+        this.checker = checker;
+    }
+
+    public List<Tag> getTagList() {
+        return subscription.getTagList();
+    }
+
+    public UUID getId() {
+        return subscription.getId();
+    }
+
+    public String getCreatedBy() {
+        return subscription.getCreatedBy();
+    }
+
+    public boolean hasTag(String tagName) {
+        return subscription.hasTag(tagName);
+    }
+
+    public DateTime getCreatedDate() {
+        return subscription.getCreatedDate();
+    }
+
+    public void addTag(TagDefinition definition) {
+        subscription.addTag(definition);
+    }
+
+    public String getFieldValue(String fieldName) {
+        return subscription.getFieldValue(fieldName);
+    }
+
+    public void addTags(List<Tag> tags) {
+        subscription.addTags(tags);
+    }
+
+    public void setFieldValue(String fieldName, String fieldValue) {
+        subscription.setFieldValue(fieldName, fieldValue);
+    }
+
+    public void clearTags() {
+        subscription.clearTags();
+    }
+
+    public void removeTag(TagDefinition definition) {
+        subscription.removeTag(definition);
+    }
+
+    public void saveFieldValue(String fieldName, String fieldValue, CallContext context) {
+        subscription.saveFieldValue(fieldName, fieldValue, context);
+    }
+
+    public boolean generateInvoice() {
+        return subscription.generateInvoice();
+    }
+
+    public boolean processPayment() {
+        return subscription.processPayment();
+    }
+
+    public List<CustomField> getFieldList() {
+        return subscription.getFieldList();
+    }
+
+    public void setFields(List<CustomField> fields) {
+        subscription.setFields(fields);
+    }
+
+    public void saveFields(List<CustomField> fields, CallContext context) {
+        subscription.saveFields(fields, context);
+    }
+
+    public void clearFields() {
+        subscription.clearFields();
+    }
+
+    public void clearPersistedFields(CallContext context) {
+        subscription.clearPersistedFields(context);
+    }
+
+    public String getObjectName() {
+        return subscription.getObjectName();
+    }
+
+    public boolean cancel(DateTime requestedDate, boolean eot, CallContext context) throws EntitlementUserApiException {
+        return subscription.cancel(requestedDate, eot, context);
+    }
+
+    public boolean uncancel(CallContext context) throws EntitlementUserApiException {
+        return subscription.uncancel(context);
+    }
+
+    public boolean changePlan(String productName, BillingPeriod term, String planSet, DateTime requestedDate,
+            CallContext context) throws EntitlementUserApiException {
+        try {
+            checker.checkBlockedChange(this);
+        } catch (BlockingApiException e) {
+            throw new EntitlementUserApiException(e, e.getCode(), e.getMessage()); 
+        }
+        return subscription.changePlan(productName, term, planSet, requestedDate, context);
+    }
+
+    public boolean recreate(PlanPhaseSpecifier spec, DateTime requestedDate, CallContext context)
+            throws EntitlementUserApiException {
+        return subscription.recreate(spec, requestedDate, context);
+    }
+
+    public UUID getBundleId() {
+        return subscription.getBundleId();
+    }
+
+    public SubscriptionState getState() {
+        return subscription.getState();
+    }
+
+    public DateTime getStartDate() {
+        return subscription.getStartDate();
+    }
+
+    public DateTime getEndDate() {
+        return subscription.getEndDate();
+    }
+
+    public Plan getCurrentPlan() {
+        return subscription.getCurrentPlan();
+    }
+
+    public PriceList getCurrentPriceList() {
+        return subscription.getCurrentPriceList();
+    }
+
+    public PlanPhase getCurrentPhase() {
+        return subscription.getCurrentPhase();
+    }
+
+    public DateTime getChargedThroughDate() {
+        return subscription.getChargedThroughDate();
+    }
+
+    public DateTime getPaidThroughDate() {
+        return subscription.getPaidThroughDate();
+    }
+
+    public ProductCategory getCategory() {
+        return subscription.getCategory();
+    }
+
+    public SubscriptionEventTransition getPendingTransition() {
+        return subscription.getPendingTransition();
+    }
+
+    public SubscriptionEventTransition getPreviousTransition() {
+        return subscription.getPreviousTransition();
+    }
+
+    public List<SubscriptionEventTransition> getBillingTransitions() {
+        return subscription.getBillingTransitions();
+    }
+
+    public BlockingState getBlockingState() {
+        if(blockingState == null) {
+            blockingState = blockingApi.getBlockingStateFor(this);
+        }
+        return blockingState;
+    }
+
+}
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingSubscriptionBundle.java b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingSubscriptionBundle.java
new file mode 100644
index 0000000..fd23104
--- /dev/null
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/api/BlockingSubscriptionBundle.java
@@ -0,0 +1,67 @@
+/*
+ * 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.junction.plumbing.api;
+
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.overdue.OverdueState;
+
+public class BlockingSubscriptionBundle implements SubscriptionBundle {
+    private final SubscriptionBundle subscriptionBundle;
+    private final BlockingApi blockingApi; 
+    
+    private BlockingState blockingState = null;
+
+    public BlockingSubscriptionBundle(SubscriptionBundle subscriptionBundle, BlockingApi blockingApi) {
+        this.subscriptionBundle = subscriptionBundle;
+        this.blockingApi = blockingApi;
+    }
+
+    public UUID getAccountId() {
+        return subscriptionBundle.getAccountId();
+    }
+
+    public UUID getId() {
+        return subscriptionBundle.getId();
+    }
+
+    public DateTime getStartDate() {
+        return subscriptionBundle.getStartDate();
+    }
+
+    public String getKey() {
+        return subscriptionBundle.getKey();
+    }
+
+    public OverdueState<SubscriptionBundle> getOverdueState() {
+        return subscriptionBundle.getOverdueState();
+    }
+
+    @Override
+    public BlockingState getBlockingState() {
+        if(blockingState == null) {
+            blockingState = blockingApi.getBlockingStateFor(this);
+        }
+        return blockingState;
+    }
+
+}
diff --git a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java
index 3a6c110..46f18d0 100644
--- a/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java
+++ b/junction/src/main/java/com/ning/billing/junction/plumbing/billing/DefaultBillingApi.java
@@ -51,15 +51,17 @@ public class DefaultBillingApi implements BillingApi {
     private final AccountUserApi accountApi;
     private final BillCycleDayCalculator bcdCalculator;
     private final EntitlementUserApi entitlementUserApi;
+    private final BlockingCalculator blockCalculator;
 
     @Inject
     public DefaultBillingApi(ChargeThruApi chargeThruApi, CallContextFactory factory, AccountUserApi accountApi, 
-            BillCycleDayCalculator bcdCalculator, EntitlementUserApi entitlementUserApi) {
+            BillCycleDayCalculator bcdCalculator, EntitlementUserApi entitlementUserApi, BlockingCalculator blockCalculator) {
         this.chargeThruApi = chargeThruApi;
         this.accountApi = accountApi;
         this.bcdCalculator = bcdCalculator;
         this.factory = factory;
         this.entitlementUserApi = entitlementUserApi;
+        this.blockCalculator = blockCalculator;
     }
 
     @Override
@@ -94,6 +96,8 @@ public class DefaultBillingApi implements BillingApi {
                 }
             }
         }
+        
+        blockCalculator.insertBlockingEvents(result);
               
         return result;
     }
diff --git a/junction/src/test/java/com/ning/billing/junction/api/blocking/TestBlockingApi.java b/junction/src/test/java/com/ning/billing/junction/api/blocking/TestBlockingApi.java
index faaa848..2870af4 100644
--- a/junction/src/test/java/com/ning/billing/junction/api/blocking/TestBlockingApi.java
+++ b/junction/src/test/java/com/ning/billing/junction/api/blocking/TestBlockingApi.java
@@ -91,12 +91,12 @@ public class TestBlockingApi {
         boolean blockEntitlement = false;
         boolean blockBilling = false;
 
-        BlockingState state1 = new BlockingState(uuid, overdueStateName, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+        BlockingState state1 = new DefaultBlockingState(uuid, overdueStateName, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
         api.setBlockingState(state1);
         clock.setDeltaFromReality(1000 * 3600 * 24);
         
         String overdueStateName2 = "NoReallyThisCantGoOn";
-        BlockingState state2 = new BlockingState(uuid, overdueStateName2, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+        BlockingState state2 = new DefaultBlockingState(uuid, overdueStateName2, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
         api.setBlockingState(state2);
         
         SubscriptionBundle bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
@@ -117,13 +117,13 @@ public class TestBlockingApi {
         boolean blockEntitlement = false;
         boolean blockBilling = false;
 
-        BlockingState state1 = new BlockingState(uuid, overdueStateName, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+        BlockingState state1 = new DefaultBlockingState(uuid, overdueStateName, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
         api.setBlockingState(state1);
         
         clock.setDeltaFromReality(1000 * 3600 * 24);
 
         String overdueStateName2 = "NoReallyThisCantGoOn";
-        BlockingState state2 = new BlockingState(uuid, overdueStateName2, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+        BlockingState state2 = new DefaultBlockingState(uuid, overdueStateName2, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
         api.setBlockingState(state2);
         
         SubscriptionBundle bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
diff --git a/junction/src/test/java/com/ning/billing/junction/blocking/MockBlockingChecker.java b/junction/src/test/java/com/ning/billing/junction/blocking/MockBlockingChecker.java
index f188a6f..bf131ae 100644
--- a/junction/src/test/java/com/ning/billing/junction/blocking/MockBlockingChecker.java
+++ b/junction/src/test/java/com/ning/billing/junction/blocking/MockBlockingChecker.java
@@ -16,67 +16,44 @@
 
 package com.ning.billing.junction.blocking;
 
-import com.ning.billing.account.api.Account;
-import com.ning.billing.entitlement.api.user.Subscription;
-import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import java.util.UUID;
+
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.Blockable.Type;
 import com.ning.billing.junction.api.BlockingApiException;
 import com.ning.billing.junction.block.BlockingChecker;
 
 public class MockBlockingChecker implements BlockingChecker {
 
     @Override
-    public void checkBlockedChange(Subscription subscription) throws BlockingApiException {
+    public void checkBlockedChange(Blockable blockable) throws BlockingApiException {
         // Intentionally blank
         
     }
 
     @Override
-    public void checkBlockedChange(SubscriptionBundle bundle) throws BlockingApiException {
-     // Intentionally blank
-        
-    }
-
-    @Override
-    public void checkBlockedChange(Account account) throws BlockingApiException {
+    public void checkBlockedEntitlement(Blockable blockable) throws BlockingApiException {
      // Intentionally blank
-        
     }
 
     @Override
-    public void checkBlockedEntitlement(Subscription subscription) throws BlockingApiException {
+    public void checkBlockedBilling(Blockable blockable) throws BlockingApiException {
      // Intentionally blank
-        
     }
 
     @Override
-    public void checkBlockedEntitlement(SubscriptionBundle bundle) throws BlockingApiException {
-     // Intentionally blank
-        
+    public void checkBlockedChange(UUID bundleId, Type type) throws BlockingApiException {
+     // Intentionally blank 
     }
 
     @Override
-    public void checkBlockedEntitlement(Account account) throws BlockingApiException {
+    public void checkBlockedEntitlement(UUID bundleId, Type type) throws BlockingApiException {
      // Intentionally blank
-        
     }
 
     @Override
-    public void checkBlockedBilling(Subscription subscription) throws BlockingApiException {
-     // Intentionally blank
-        
-    }
-
-    @Override
-    public void checkBlockedBilling(SubscriptionBundle bundleId) throws BlockingApiException {
-     // Intentionally blank
-        
-    }
-
-    @Override
-    public void checkBlockedBilling(Account account) throws BlockingApiException {
-     // Intentionally blank
-        
+    public void checkBlockedBilling(UUID bundleId, Type type) throws BlockingApiException {
+     // Intentionally blank 
     }
 
-   
 }
diff --git a/junction/src/test/java/com/ning/billing/junction/blocking/TestBlockingChecker.java b/junction/src/test/java/com/ning/billing/junction/blocking/TestBlockingChecker.java
index b973bba..c9d6a4e 100644
--- a/junction/src/test/java/com/ning/billing/junction/blocking/TestBlockingChecker.java
+++ b/junction/src/test/java/com/ning/billing/junction/blocking/TestBlockingChecker.java
@@ -35,6 +35,7 @@ import com.ning.billing.junction.api.Blockable;
 import com.ning.billing.junction.api.Blockable.Type;
 import com.ning.billing.junction.api.BlockingApiException;
 import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.junction.api.blocking.DefaultBlockingState;
 import com.ning.billing.junction.block.BlockingChecker;
 import com.ning.billing.junction.block.DefaultBlockingChecker;
 import com.ning.billing.junction.dao.BlockingStateDao;
@@ -117,7 +118,6 @@ public class TestBlockingChecker {
                 bind(BlockingStateDao.class).toInstance(dao);             
                 
                 EntitlementUserApi entitlementUserApi = BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementUserApi.class);
-                //((ZombieControl) entitlementDao).addResult("", result)
                 bind(EntitlementUserApi.class).toInstance(entitlementUserApi);
                 ((ZombieControl) entitlementUserApi).addResult("getBundleFromId",bundle);
                 
@@ -129,15 +129,17 @@ public class TestBlockingChecker {
 
 
     private void setStateBundle(boolean bC, boolean bE, boolean bB) {
-        bundleState = new BlockingState(UUID.randomUUID(), "state", Blockable.Type.SUBSCRIPTION_BUNDLE, "test-service", bC, bE,bB);
+        bundleState = new DefaultBlockingState(UUID.randomUUID(), "state", Blockable.Type.SUBSCRIPTION_BUNDLE, "test-service", bC, bE,bB);
+        ((ZombieControl) bundle).addResult("getBlockingState", bundleState);
     }
 
     private void setStateAccount(boolean bC, boolean bE, boolean bB) {
-        accountState = new BlockingState(UUID.randomUUID(), "state", Blockable.Type.SUBSCRIPTION_BUNDLE, "test-service", bC, bE,bB);
+        accountState = new DefaultBlockingState(UUID.randomUUID(), "state", Blockable.Type.SUBSCRIPTION_BUNDLE, "test-service", bC, bE,bB);
     }
 
     private void setStateSubscription(boolean bC, boolean bE, boolean bB) {
-        subscriptionState = new BlockingState(UUID.randomUUID(), "state", Blockable.Type.SUBSCRIPTION_BUNDLE, "test-service", bC, bE,bB);
+        subscriptionState = new DefaultBlockingState(UUID.randomUUID(), "state", Blockable.Type.SUBSCRIPTION_BUNDLE, "test-service", bC, bE,bB);
+        ((ZombieControl) subscription).addResult("getBlockingState", subscriptionState);
     }
 
     @Test(groups={"fast"}, enabled = true)
diff --git a/junction/src/test/java/com/ning/billing/junction/dao/TestBlockingDao.java b/junction/src/test/java/com/ning/billing/junction/dao/TestBlockingDao.java
index 084f30f..b9be954 100644
--- a/junction/src/test/java/com/ning/billing/junction/dao/TestBlockingDao.java
+++ b/junction/src/test/java/com/ning/billing/junction/dao/TestBlockingDao.java
@@ -35,6 +35,7 @@ import com.ning.billing.entitlement.api.user.SubscriptionBundle;
 import com.ning.billing.junction.MockModule;
 import com.ning.billing.junction.api.Blockable;
 import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.junction.api.blocking.DefaultBlockingState;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
 import com.ning.billing.util.clock.ClockMock;
@@ -78,12 +79,12 @@ public class TestBlockingDao {
         boolean blockEntitlement = false;
         boolean blockBilling = false;
 
-        BlockingState state1 = new BlockingState(uuid, overdueStateName, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+        BlockingState state1 = new DefaultBlockingState(uuid, overdueStateName, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
         dao.setBlockingState(state1, clock);
         clock.setDeltaFromReality(1000 * 3600 * 24);
         
         String overdueStateName2 = "NoReallyThisCantGoOn";
-        BlockingState state2 = new BlockingState(uuid, overdueStateName2, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+        BlockingState state2 = new DefaultBlockingState(uuid, overdueStateName2, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
         dao.setBlockingState(state2, clock);
         
         SubscriptionBundle bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
@@ -105,12 +106,12 @@ public class TestBlockingDao {
         boolean blockEntitlement = false;
         boolean blockBilling = false;
 
-        BlockingState state1 = new BlockingState(uuid, overdueStateName, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+        BlockingState state1 = new DefaultBlockingState(uuid, overdueStateName, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
         dao.setBlockingState(state1, clock);
         clock.setDeltaFromReality(1000 * 3600 * 24);
         
         String overdueStateName2 = "NoReallyThisCantGoOn";
-        BlockingState state2 = new BlockingState(uuid, overdueStateName2, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
+        BlockingState state2 = new DefaultBlockingState(uuid, overdueStateName2, Blockable.Type.SUBSCRIPTION_BUNDLE, service, blockChange, blockEntitlement,blockBilling);
         dao.setBlockingState(state2, clock);
         
         SubscriptionBundle bundle = BrainDeadProxyFactory.createBrainDeadProxyFor(SubscriptionBundle.class);
diff --git a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java
new file mode 100644
index 0000000..de9a18c
--- /dev/null
+++ b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestBlockingCalculator.java
@@ -0,0 +1,735 @@
+/*
+ * 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.junction.plumbing.billing;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.catalog.MockPlan;
+import com.ning.billing.catalog.MockPlanPhase;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.entitlement.api.billing.BillingEvent;
+import com.ning.billing.entitlement.api.billing.BillingModeType;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionEventTransition.SubscriptionTransitionType;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.Blockable.Type;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.junction.api.blocking.DefaultBlockingState;
+import com.ning.billing.junction.dao.BlockingStateDao;
+import com.ning.billing.junction.plumbing.billing.BlockingCalculator.DisabledDuration;
+import com.ning.billing.mock.BrainDeadProxyFactory;
+import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.ClockMock;
+
+
+public class TestBlockingCalculator {
+
+    private static final String DISABLED_BUNDLE = "disabled-bundle";
+    private static final String CLEAR_BUNDLE = "clear-bundle";
+
+    private BlockingApi blockingApi;
+    private Account account;
+    private Subscription subscription1;
+    private Subscription subscription2;
+    private Subscription subscription3;
+    private Subscription subscription4;
+    private UUID bundleId1 = UUID.randomUUID();
+    private UUID bundleId2 = UUID.randomUUID();
+    private Clock clock;
+    private BlockingCalculator odc;
+
+    @BeforeClass
+    public void setUpBeforeClass() throws Exception {
+
+        clock = new ClockMock();
+        
+        Injector i = Guice.createInjector(new AbstractModule() {
+
+            @Override
+            protected void configure() {
+                blockingApi = BrainDeadProxyFactory.createBrainDeadProxyFor(BlockingApi.class);
+                account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
+                subscription1 = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class, Comparable.class);
+                subscription2 = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class, Comparable.class);
+                subscription3 = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class, Comparable.class);
+                subscription4 = BrainDeadProxyFactory.createBrainDeadProxyFor(Subscription.class, Comparable.class);
+                ((ZombieControl) account).addResult("getId", UUID.randomUUID());
+                ((ZombieControl) subscription1).addResult("getBundleId", bundleId1);
+                ((ZombieControl) subscription2).addResult("getBundleId", bundleId1);
+                ((ZombieControl) subscription3).addResult("getBundleId", bundleId1);
+                ((ZombieControl) subscription4).addResult("getBundleId", bundleId2);
+                ((ZombieControl) subscription1).addResult("compareTo", 1);
+                ((ZombieControl) subscription2).addResult("compareTo", 1);
+                ((ZombieControl) subscription3).addResult("compareTo", 1);
+                ((ZombieControl) subscription4).addResult("compareTo", 1);
+                ((ZombieControl) subscription1).addResult("getId", UUID.randomUUID());
+                ((ZombieControl) subscription2).addResult("getId", UUID.randomUUID());
+                ((ZombieControl) subscription3).addResult("getId", UUID.randomUUID());
+                ((ZombieControl) subscription4).addResult("getId", UUID.randomUUID());
+         
+         
+                bind(BlockingStateDao.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(BlockingStateDao.class));
+                bind(BlockingApi.class).toInstance(blockingApi);              
+                              
+            }
+            
+        });
+        odc = i.getInstance(BlockingCalculator.class);
+
+    }
+
+    @Test
+    // S1-S2-S3 subscriptions in B1
+    // B1 -----[--------]
+    // S1 --A-------------------------------------
+    // S2 --B------C------------------------------
+    // S3 ------------------D---------------------
+    
+
+    //Result
+    // S1 --A--[-------]--------------------------
+    // S2 --B--[-------]--------------------------
+    // S3 ------------------D---------------------
+    
+    public void testInsertBlockingEvents() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, null));
+        BillingEvent A = createRealEvent(now.minusDays(1).minusHours(1), subscription1);
+        BillingEvent B = createRealEvent(now.minusDays(1), subscription2);
+        BillingEvent C = createRealEvent(now.plusDays(1), subscription2);
+        BillingEvent D = createRealEvent(now.plusDays(3), subscription3);
+        billingEvents.add(A);
+        billingEvents.add(B);
+        billingEvents.add(C);
+        billingEvents.add(D);
+
+        SortedSet<BlockingState> blockingStates = new TreeSet<BlockingState>();
+        blockingStates.add(new DefaultBlockingState(bundleId1,DISABLED_BUNDLE, Blockable.Type.SUBSCRIPTION_BUNDLE, "test", true, true, true, now));
+        blockingStates.add(new DefaultBlockingState(bundleId1,CLEAR_BUNDLE, Blockable.Type.SUBSCRIPTION_BUNDLE, "test", false, false, false, now.plusDays(2)));
+        
+        ((ZombieControl)blockingApi).addResult("getBlockingHistory", blockingStates);
+        
+        
+        odc.insertBlockingEvents(billingEvents);
+        
+        assertEquals(billingEvents.size(), 7);
+        
+        SortedSet<BillingEvent> s1Events = odc.filter(billingEvents, subscription1);
+        Iterator<BillingEvent> it1 = s1Events.iterator();
+        assertEquals(it1.next(), A);
+        assertEquals(it1.next().getTransitionType(), SubscriptionTransitionType.CANCEL);
+        assertEquals(it1.next().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+        
+        SortedSet<BillingEvent> s2Events = odc.filter(billingEvents, subscription2);
+        Iterator<BillingEvent> it2 = s2Events.iterator();       
+        assertEquals(it2.next(), B);
+        assertEquals(it2.next().getTransitionType(), SubscriptionTransitionType.CANCEL);
+        assertEquals(it2.next().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+                
+        SortedSet<BillingEvent> s3Events = odc.filter(billingEvents, subscription3);
+        Iterator<BillingEvent> it3 = s3Events.iterator();       
+        assertEquals(it3.next(),D);
+    }
+
+    // Open ended duration with a previous event
+    // --X--[----------------------------------
+   @Test
+    public void testEventsToRemoveOpenPrev() {
+       DateTime now = clock.getUTCNow();
+       List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+       SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+       
+       disabledDuration.add(new DisabledDuration(now, null));
+       billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
+       
+       SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+       
+       assertEquals(results.size(), 0);
+   }
+
+   // Open with previous and following events
+   // --X--[----Y-----------------------------
+    @Test
+    public void testEventsToRemoveOpenPrevFollow() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, null));
+        BillingEvent e1 = createRealEvent(now.minusDays(1), subscription1);
+        BillingEvent e2  = createRealEvent(now.plusDays(1), subscription1);
+        billingEvents.add(e1);
+        billingEvents.add(e2);
+        
+        SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents,  subscription1);
+        
+        assertEquals(results.size(), 1);
+        assertEquals(results.first(), e2);
+    }
+
+    // Open with no previous event (only following)
+    // -----[----X-----------------------------
+    @Test
+    public void testEventsToRemoveOpenFollow() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, null));
+        BillingEvent e1  = createRealEvent(now.plusDays(1), subscription1);
+        billingEvents.add(e1);
+        
+        SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents,  subscription1);
+        
+        assertEquals(results.size(), 1);
+        assertEquals(results.first(), e1);
+   }
+
+    // Closed duration with a single previous event
+    // --X--[------------]---------------------
+        @Test
+    public void testEventsToRemoveClosedPrev() {
+            DateTime now = clock.getUTCNow();
+            List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+            SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+            
+            disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+            BillingEvent e1  = createRealEvent(now.minusDays(1), subscription1);
+            billingEvents.add(e1);
+            
+            SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents,  subscription1);
+            
+            assertEquals(results.size(), 0);
+    }
+
+    // Closed duration with a previous event and in-between event
+    // --X--[------Y-----]---------------------
+    @Test
+    public void testEventsToRemoveClosedPrevBetw() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+        BillingEvent e1 = createRealEvent(now.minusDays(1), subscription1);
+        BillingEvent e2  = createRealEvent(now.plusDays(1), subscription1);
+        billingEvents.add(e1);
+        billingEvents.add(e2);        
+       
+        
+        SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+        
+        assertEquals(results.size(), 1);
+        assertEquals(results.first(), e2);
+    }
+
+    // Closed duration with a previous event and in-between event and following
+    // --X--[------Y-----]-------Z-------------
+    @Test
+    public void testEventsToRemoveClosedPrevBetwNext() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+        BillingEvent e1 = createRealEvent(now.minusDays(1), subscription1);
+        BillingEvent e2  = createRealEvent(now.plusDays(1), subscription1);
+        BillingEvent e3  = createRealEvent(now.plusDays(3), subscription1);
+        billingEvents.add(e1);
+        billingEvents.add(e2);        
+        billingEvents.add(e3);        
+        
+        SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+        
+        assertEquals(results.size(), 1);
+        assertEquals(results.first(), e2);
+   }
+
+    // Closed with no previous event but in-between events
+    // -----[------Y-----]---------------------
+    @Test
+    public void testEventsToRemoveClosedBetwn() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+        BillingEvent e2  = createRealEvent(now.plusDays(1), subscription1);
+        billingEvents.add(e2);        
+      
+        
+        SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+        
+        assertEquals(results.size(), 1);
+        assertEquals(results.first(), e2);
+    }
+
+    // Closed with no previous event but in-between events and following
+    // -----[------Y-----]-------Z-------------
+    @Test
+    public void testEventsToRemoveClosedBetweenFollow() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+
+        BillingEvent e2  = createRealEvent(now.plusDays(1), subscription1);
+        BillingEvent e3  = createRealEvent(now.plusDays(3), subscription1);
+        billingEvents.add(e2);        
+        billingEvents.add(e3);        
+        
+        SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+        
+        assertEquals(results.size(), 1);
+        assertEquals(results.first(), e2);
+    }
+
+    // Closed duration with only following
+    // -----[------------]-------Z-------------
+    @Test
+    public void testEventsToRemoveClosedFollow() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+
+        BillingEvent e3  = createRealEvent(now.plusDays(3), subscription1);
+       
+        billingEvents.add(e3);        
+        
+        SortedSet<BillingEvent> results = odc.eventsToRemove( disabledDuration, billingEvents, subscription1);
+        
+        assertEquals(results.size(), 0);
+     }
+    
+    // Open ended duration with a previous event
+    // --X--[----------------------------------
+   @Test
+    public void testCreateNewEventsOpenPrev() {
+       DateTime now = clock.getUTCNow();
+       List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+       SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+       
+       disabledDuration.add(new DisabledDuration(now, null));
+       billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
+       
+       SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents,  account, subscription1);
+       
+       assertEquals(results.size(), 1);
+       assertEquals(results.first().getEffectiveDate(), now);
+       assertEquals(results.first().getRecurringPrice(), BigDecimal.ZERO);
+       assertEquals(results.first().getTransitionType(), SubscriptionTransitionType.CANCEL);
+   }
+
+   // Open with previous and following events
+   // --X--[----Y-----------------------------
+    @Test
+    public void testCreateNewEventsOpenPrevFollow() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, null));
+        billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
+        billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
+        
+        SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents,  account, subscription1);
+        
+        assertEquals(results.size(), 1);
+        assertEquals(results.first().getEffectiveDate(), now);
+        assertEquals(results.first().getRecurringPrice(), BigDecimal.ZERO);
+        assertEquals(results.first().getTransitionType(), SubscriptionTransitionType.CANCEL);
+    }
+
+    // Open with no previous event (only following)
+    // -----[----X-----------------------------
+    @Test
+    public void testCreateNewEventsOpenFollow() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, null));
+        billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
+        
+        SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents,  account, subscription1);
+        
+        assertEquals(results.size(), 0);
+   }
+
+    // Closed duration with a single previous event
+    // --X--[------------]---------------------
+        @Test
+    public void testCreateNewEventsClosedPrev() {
+            DateTime now = clock.getUTCNow();
+            List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+            SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+            
+            disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+            billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
+            
+            SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents,  account, subscription1);
+            
+            assertEquals(results.size(), 2);
+            assertEquals(results.first().getEffectiveDate(), now);
+            assertEquals(results.first().getRecurringPrice(), BigDecimal.ZERO);
+            assertEquals(results.first().getTransitionType(), SubscriptionTransitionType.CANCEL);
+            assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
+            assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+            assertEquals(results.last().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+    }
+
+    // Closed duration with a previous event and in-between event
+    // --X--[------Y-----]---------------------
+    @Test
+    public void testCreateNewEventsClosedPrevBetw() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+        billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
+        billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
+        
+        SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents,  account, subscription1);
+        
+        assertEquals(results.size(), 2);
+        assertEquals(results.first().getEffectiveDate(), now);
+        assertEquals(results.first().getRecurringPrice(), BigDecimal.ZERO);
+        assertEquals(results.first().getTransitionType(), SubscriptionTransitionType.CANCEL);
+        assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
+        assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+        assertEquals(results.last().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+    }
+
+    // Closed duration with a previous event and in-between event and following
+    // --X--[------Y-----]-------Z-------------
+    @Test
+    public void testCreateNewEventsClosedPrevBetwNext() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+        billingEvents.add(createRealEvent(now.minusDays(1), subscription1));
+        billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
+        billingEvents.add(createRealEvent(now.plusDays(3), subscription1));
+        
+        SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents,  account, subscription1);
+        
+        assertEquals(results.size(), 2);
+        assertEquals(results.first().getEffectiveDate(), now);
+        assertEquals(results.first().getRecurringPrice(), BigDecimal.ZERO);
+        assertEquals(results.first().getTransitionType(), SubscriptionTransitionType.CANCEL);
+        assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
+        assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+        assertEquals(results.last().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+   }
+
+    // Closed with no previous event but in-between events
+    // -----[------Y-----]---------------------
+    @Test
+    public void testCreateNewEventsClosedBetwn() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+        billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
+        
+        SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents,  account, subscription1);
+        
+        assertEquals(results.size(), 1);
+        assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
+        assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+        assertEquals(results.last().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+    }
+
+    // Closed with no previous event but in-between events and following
+    // -----[------Y-----]-------Z-------------
+    @Test
+    public void testCreateNewEventsClosedBetweenFollow() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+        billingEvents.add(createRealEvent(now.plusDays(1), subscription1));
+        
+        SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents,  account, subscription1);
+        
+        assertEquals(results.size(), 1);
+        assertEquals(results.last().getEffectiveDate(), now.plusDays(2));
+        assertEquals(results.last().getRecurringPrice(), billingEvents.first().getRecurringPrice());
+        assertEquals(results.last().getTransitionType(), SubscriptionTransitionType.RE_CREATE);
+    }
+
+    // Closed duration with only following
+    // -----[------------]-------Z-------------
+    @Test
+    public void testCreateNewEventsClosedFollow() {
+        DateTime now = clock.getUTCNow();
+        List<DisabledDuration> disabledDuration = new ArrayList<BlockingCalculator.DisabledDuration>();
+        SortedSet<BillingEvent> billingEvents = new TreeSet<BillingEvent>();
+        
+        disabledDuration.add(new DisabledDuration(now, now.plusDays(2)));
+        billingEvents.add(createRealEvent(now.plusDays(3), subscription1));
+        
+        SortedSet<BillingEvent> results = odc.createNewEvents( disabledDuration, billingEvents,  account, subscription1);
+        
+        assertEquals(results.size(), 0);
+     }
+
+    @Test
+    public void testPrecedingBillingEventForSubscription() {
+        DateTime now = new DateTime();
+        
+        SortedSet<BillingEvent> events = new TreeSet<BillingEvent>();
+
+        events.add(createRealEvent(now.minusDays(10), subscription1));
+        events.add(createRealEvent(now.minusDays(6), subscription1));
+        events.add(createRealEvent(now.minusDays(5), subscription1));
+        events.add(createRealEvent(now.minusDays(1), subscription1));
+        
+        BillingEvent minus11 = odc.precedingBillingEventForSubscription(now.minusDays(11), events, subscription1);
+        assertNull(minus11);
+        
+        BillingEvent minus5andAHalf= odc.precedingBillingEventForSubscription(now.minusDays(5).minusHours(12), events, subscription1);
+        assertNotNull(minus5andAHalf);
+        assertEquals(minus5andAHalf.getEffectiveDate(), now.minusDays(6));
+      
+        
+    }
+    
+    protected BillingEvent createRealEvent(DateTime effectiveDate, Subscription subscription) {
+        final Account account = this.account;
+        final int billCycleDay = 1;
+        final PlanPhase planPhase = new MockPlanPhase();
+        final Plan plan = new MockPlan();
+        final BigDecimal fixedPrice = BigDecimal.TEN;
+        final BigDecimal recurringPrice = BigDecimal.TEN;
+        final Currency currency = Currency.USD;
+        final String description = "";
+        final BillingModeType billingModeType = BillingModeType.IN_ADVANCE;
+        final BillingPeriod billingPeriod = BillingPeriod.MONTHLY;
+        final SubscriptionTransitionType type = SubscriptionTransitionType.CHANGE;
+        final Long totalOrdering = 0L; //TODO
+
+        return new DefaultBillingEvent(account, subscription, effectiveDate, plan, planPhase,
+                fixedPrice, recurringPrice, currency,
+                billingPeriod, billCycleDay, billingModeType,
+                description, totalOrdering, type);
+    }
+
+
+    @Test
+    public void testFilter() {
+        SortedSet<BillingEvent> events = new TreeSet<BillingEvent>();
+        
+        events.add(createBillingEvent(subscription1));
+        events.add(createBillingEvent(subscription1));
+        events.add(createBillingEvent(subscription1));
+        events.add(createBillingEvent(subscription2));
+        
+        SortedSet<BillingEvent> result1 = odc.filter(events, subscription1);
+        SortedSet<BillingEvent> result2 = odc.filter(events, subscription2);
+        SortedSet<BillingEvent> result3 = odc.filter(events, subscription3);
+        
+        assertEquals(result1.size(), 3);
+        assertEquals(result1.first().getSubscription(), subscription1);
+        assertEquals(result1.last().getSubscription(), subscription1);
+        assertEquals(result2.size(), 1);
+        assertEquals(result2.first().getSubscription(), subscription2);
+        assertEquals(result3.size(), 0);
+    }
+
+    @Test
+    public void testCreateNewDisableEvent() {
+        DateTime now = clock.getUTCNow();
+        BillingEvent event = new MockBillingEvent();
+        
+        BillingEvent result = odc.createNewDisableEvent(now, event);
+        assertEquals(result.getBillCycleDay(),event.getBillCycleDay());
+        assertEquals(result.getEffectiveDate(), now);
+        assertEquals(result.getPlanPhase(), event.getPlanPhase());
+        assertEquals(result.getPlan(), event.getPlan());
+        assertEquals(result.getFixedPrice(),BigDecimal.ZERO);
+        assertEquals(result.getRecurringPrice(), BigDecimal.ZERO);
+        assertEquals(result.getCurrency(), event.getCurrency());
+        assertEquals(result.getDescription(), "");
+        assertEquals(result.getBillingMode(), event.getBillingMode());
+        assertEquals(result.getBillingPeriod(), event.getBillingPeriod());
+        assertEquals(result.getTransitionType(),  SubscriptionTransitionType.CANCEL);
+        assertEquals(result.getTotalOrdering(), new Long(0));
+    }
+
+    @Test
+    public void testCreateNewReenableEvent() {
+        DateTime now = clock.getUTCNow();
+        BillingEvent event = new MockBillingEvent();
+        
+        BillingEvent result = odc.createNewReenableEvent(now, event);
+        assertEquals(result.getBillCycleDay(),event.getBillCycleDay());
+        assertEquals(result.getEffectiveDate(), now);
+        assertEquals(result.getPlanPhase(), event.getPlanPhase());
+        assertEquals(result.getPlan(), event.getPlan());
+        assertEquals(result.getFixedPrice(),event.getFixedPrice());
+        assertEquals(result.getRecurringPrice(), event.getRecurringPrice());
+        assertEquals(result.getCurrency(), event.getCurrency());
+        assertEquals(result.getDescription(), "");
+        assertEquals(result.getBillingMode(), event.getBillingMode());
+        assertEquals(result.getBillingPeriod(), event.getBillingPeriod());
+        assertEquals(result.getTransitionType(),  SubscriptionTransitionType.RE_CREATE);
+        assertEquals(result.getTotalOrdering(), new Long(0));
+    }
+    
+    private class MockBillingEvent extends DefaultBillingEvent {
+        public MockBillingEvent() {
+            super(account, subscription1, clock.getUTCNow(), null, null, BigDecimal.ZERO, BigDecimal.TEN, Currency.USD, BillingPeriod.ANNUAL,
+                    4, BillingModeType.IN_ADVANCE, "", 3L, SubscriptionTransitionType.CREATE);
+        }        
+    }
+
+    @Test
+    public void testCreateBundleSubscriptionMap() {
+        SortedSet<BillingEvent> events = new TreeSet<BillingEvent>();
+        events.add(createBillingEvent(subscription1));
+        events.add(createBillingEvent(subscription2));
+        events.add(createBillingEvent(subscription3));
+        events.add(createBillingEvent(subscription4));
+        
+        Hashtable<UUID,List<Subscription>> map = odc.createBundleSubscriptionMap(events);
+        
+        assertNotNull(map);
+        assertEquals(map.keySet().size(),2);
+        assertEquals(map.get(bundleId1).size(), 3);
+        assertEquals(map.get(bundleId2).size(), 1);
+        
+    }
+
+    private BillingEvent createBillingEvent(Subscription subscription) {
+        BillingEvent result =  BrainDeadProxyFactory.createBrainDeadProxyFor(BillingEvent.class, Comparable.class);
+        ((ZombieControl)result).addResult("getSubscription", subscription);
+        ((ZombieControl)result).addResult("compareTo", 1);
+        return result;
+    }
+
+    @Test
+    public void testCreateDisablePairs() {
+        SortedSet<BlockingState> blockingEvents;
+        UUID ovdId = UUID.randomUUID();
+        DateTime now = clock.getUTCNow();
+        
+        //simple events open clear -> disabled
+        blockingEvents = new TreeSet<BlockingState>();
+        blockingEvents.add(new DefaultBlockingState(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,"test", false, false, false, now));
+        blockingEvents.add(new DefaultBlockingState(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE, "test", true, true, true,now.plusDays(1)));
+        
+        List<DisabledDuration> pairs = odc.createBlockingDurations(blockingEvents);
+        assertEquals(pairs.size(), 1);
+        assertNotNull(pairs.get(0).getStart());
+        assertEquals(pairs.get(0).getStart(),now.plusDays(1));
+        assertNull(pairs.get(0).getEnd());
+        
+        //simple events closed clear -> disabled
+        blockingEvents = new TreeSet<BlockingState>();
+        blockingEvents.add(new DefaultBlockingState(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,"test", false, false, false,now));
+        blockingEvents.add(new DefaultBlockingState(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE, "test", true, true, true,now.plusDays(1)));
+        blockingEvents.add(new DefaultBlockingState(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,"test", false, false, false,now.plusDays(2)));
+        
+        pairs = odc.createBlockingDurations(blockingEvents);
+        assertEquals(pairs.size(), 1);
+        assertNotNull(pairs.get(0).getStart());
+        assertEquals(pairs.get(0).getStart(),now.plusDays(1));
+        assertNotNull(pairs.get(0).getEnd());
+        assertEquals(pairs.get(0).getEnd(),now.plusDays(2));
+
+        //simple BUNDLE events closed clear -> disabled
+        blockingEvents = new TreeSet<BlockingState>();
+        blockingEvents.add(new DefaultBlockingState(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,"test", false, false, false,now));
+        blockingEvents.add(new DefaultBlockingState(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE, "test", true, true, true,now.plusDays(1)));
+        blockingEvents.add(new DefaultBlockingState(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,"test", false, false, false,now.plusDays(2)));
+        
+        pairs = odc.createBlockingDurations(blockingEvents);
+        assertEquals(pairs.size(), 1);
+        assertNotNull(pairs.get(0).getStart());
+        assertEquals(pairs.get(0).getStart(),now.plusDays(1));
+        assertNotNull(pairs.get(0).getEnd());
+        assertEquals(pairs.get(0).getEnd(),now.plusDays(2));
+        
+        
+        //two or more disableds in a row
+        blockingEvents = new TreeSet<BlockingState>();
+        blockingEvents.add(new DefaultBlockingState(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,"test", false, false, false,now));
+        blockingEvents.add(new DefaultBlockingState(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE, "test", true, true, true,now.plusDays(1)));
+        blockingEvents.add(new DefaultBlockingState(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE, "test", true, true, true,now.plusDays(2)));
+        blockingEvents.add(new DefaultBlockingState(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,"test", false, false, false,now.plusDays(3)));
+        
+        pairs = odc.createBlockingDurations(blockingEvents);
+        assertEquals(pairs.size(), 1);
+        assertNotNull(pairs.get(0).getStart());
+        assertEquals(pairs.get(0).getStart(),now.plusDays(1));
+        assertNotNull(pairs.get(0).getEnd());
+        assertEquals(pairs.get(0).getEnd(),now.plusDays(3));
+
+       
+        blockingEvents = new TreeSet<BlockingState>();
+        blockingEvents.add(new DefaultBlockingState(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,"test", false, false, false,now));
+        blockingEvents.add(new DefaultBlockingState(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE, "test", true, true, true,now.plusDays(1)));
+        blockingEvents.add(new DefaultBlockingState(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE, "test", true, true, true,now.plusDays(2)));
+        blockingEvents.add(new DefaultBlockingState(ovdId,DISABLED_BUNDLE, Type.SUBSCRIPTION_BUNDLE, "test", true, true, true,now.plusDays(3)));
+        blockingEvents.add(new DefaultBlockingState(ovdId,CLEAR_BUNDLE, Type.SUBSCRIPTION_BUNDLE,"test", false, false, false,now.plusDays(4)));
+        
+        pairs = odc.createBlockingDurations(blockingEvents);
+        assertEquals(pairs.size(), 1);
+        assertNotNull(pairs.get(0).getStart());
+        assertEquals(pairs.get(0).getStart(),now.plusDays(1));
+        assertNotNull(pairs.get(0).getEnd());
+        assertEquals(pairs.get(0).getEnd(),now.plusDays(4));
+  
+    }
+}
diff --git a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestDefaultEntitlementBillingApi.java b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestDefaultEntitlementBillingApi.java
index 59ea10d..044fe43 100644
--- a/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestDefaultEntitlementBillingApi.java
+++ b/junction/src/test/java/com/ning/billing/junction/plumbing/billing/TestDefaultEntitlementBillingApi.java
@@ -20,9 +20,12 @@ package com.ning.billing.junction.plumbing.billing;
 import static org.testng.Assert.assertNull;
 import static org.testng.Assert.assertTrue;
 
+import java.math.BigDecimal;
 import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 import java.util.SortedSet;
+import java.util.TreeSet;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
@@ -34,15 +37,17 @@ import org.testng.annotations.Test;
 
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountUserApi;
-import com.ning.billing.catalog.DefaultCatalogService;
 import com.ning.billing.catalog.MockCatalog;
 import com.ning.billing.catalog.MockCatalogService;
 import com.ning.billing.catalog.api.BillingAlignment;
 import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.CatalogService;
 import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.CurrencyValueNull;
+import com.ning.billing.catalog.api.InternationalPrice;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.Price;
 import com.ning.billing.catalog.api.PriceList;
 import com.ning.billing.catalog.api.PriceListSet;
 import com.ning.billing.entitlement.api.billing.BillingEvent;
@@ -59,6 +64,11 @@ import com.ning.billing.entitlement.api.user.SubscriptionTransitionData;
 import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
 import com.ning.billing.entitlement.events.user.ApiEventType;
 import com.ning.billing.junction.api.BillingApi;
+import com.ning.billing.junction.api.Blockable;
+import com.ning.billing.junction.api.Blockable.Type;
+import com.ning.billing.junction.api.BlockingApi;
+import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.junction.api.blocking.DefaultBlockingState;
 import com.ning.billing.lifecycle.KillbillService.ServiceException;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
@@ -68,15 +78,63 @@ import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.clock.ClockMock;
 
 public class TestDefaultEntitlementBillingApi {
-	private static final UUID zeroId = new UUID(0L,0L);
-	private static final UUID oneId = new UUID(1L,0L);
-	private static final UUID twoId = new UUID(2L,0L);
+    
+    class MockPrice implements InternationalPrice {
+        private final BigDecimal price;
+        
+        public MockPrice(String val) {
+            price = new BigDecimal(val);
+        }
+        
+        @Override
+        public boolean isZero() {
+            return price.compareTo(BigDecimal.ZERO) == 0;
+        }
+        
+        @Override
+        public Price[] getPrices() {
+            return new Price[]{ 
+                    new Price() {
+
+                        @Override
+                        public Currency getCurrency() {
+                            return Currency.USD;
+                        }
+
+                        @Override
+                        public BigDecimal getValue() throws CurrencyValueNull {
+                            return price;
+                        }
+
+                    }
+            };
+        }
+        
+        @Override
+        public BigDecimal getPrice(Currency currency) throws CatalogApiException {
+             return price;
+        }
+    };
+    
+    private static final String DISABLED_BUNDLE = "disabled-bundle";
+    private static final String CLEAR_BUNDLE = "clear-bundle";
+
+	private static final UUID eventId = new UUID(0L,0L);
+	private static final UUID subId = new UUID(1L,0L);
+	private static final UUID bunId = new UUID(2L,0L);
 
 	private CatalogService catalogService;
 	private ArrayList<SubscriptionBundle> bundles;
 	private ArrayList<Subscription> subscriptions;
 	private ArrayList<SubscriptionEventTransition> transitions;
-	private EntitlementUserApi entitlementApi;
+    private EntitlementUserApi entitlementApi;
+    private BlockingCalculator blockCalculator = new BlockingCalculator(null) {
+        @Override
+        public void insertBlockingEvents(SortedSet<BillingEvent> billingEvents) {
+           
+        }
+        
+    };
 
 	private Clock clock;
 	private Subscription subscription;
@@ -91,7 +149,7 @@ public class TestDefaultEntitlementBillingApi {
 	@BeforeMethod(alwaysRun=true)
 	public void setupEveryTime() {
 		bundles = new ArrayList<SubscriptionBundle>();
-		final SubscriptionBundle bundle = new SubscriptionBundleData( zeroId,"TestKey", oneId,  clock.getUTCNow().minusDays(4), null);
+		final SubscriptionBundle bundle = new SubscriptionBundleData( eventId,"TestKey", subId,  clock.getUTCNow().minusDays(4), null);
 		bundles.add(bundle);
 
 
@@ -100,7 +158,7 @@ public class TestDefaultEntitlementBillingApi {
 
 		SubscriptionBuilder builder = new SubscriptionBuilder();
 		subscriptionStartDate = clock.getUTCNow().minusDays(3);
-		builder.setStartDate(subscriptionStartDate).setId(oneId);
+		builder.setStartDate(subscriptionStartDate).setId(subId).setBundleId(bunId);
 		subscription = new SubscriptionData(builder) {
 		    @Override
             public List<SubscriptionEventTransition> getBillingTransitions() {
@@ -131,7 +189,7 @@ public class TestDefaultEntitlementBillingApi {
 
         BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
         CallContextFactory factory = new DefaultCallContextFactory(clock);
-		BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi);
+		BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi, blockCalculator);
 		SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
 		Assert.assertEquals(events.size(), 0);
 	}
@@ -144,7 +202,7 @@ public class TestDefaultEntitlementBillingApi {
 		PlanPhase nextPhase = nextPlan.getAllPhases()[0]; // The trial has no billing period
         PriceList nextPriceList = catalogService.getFullCatalog().findPriceList(PriceListSet.DEFAULT_PRICELIST_NAME, now);
 		SubscriptionEventTransition t = new SubscriptionTransitionData(
-				zeroId, oneId, twoId, EventType.API_USER, ApiEventType.CREATE, then, now, null, null, null, null, SubscriptionState.ACTIVE, nextPlan, nextPhase, nextPriceList, 1, null, true);
+				eventId, subId, bunId, EventType.API_USER, ApiEventType.CREATE, then, now, null, null, null, null, SubscriptionState.ACTIVE, nextPlan, nextPhase, nextPriceList, 1, null, true);
 		transitions.add(t);
 
 
@@ -156,10 +214,10 @@ public class TestDefaultEntitlementBillingApi {
 		       
         BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
         CallContextFactory factory = new DefaultCallContextFactory(clock);
-        BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi);
+        BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi, blockCalculator);
         SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
 
-		checkFirstEvent(events, nextPlan, 32, oneId, now, nextPhase, ApiEventType.CREATE.toString());
+		checkFirstEvent(events, nextPlan, 32, subId, now, nextPhase, ApiEventType.CREATE.toString());
 	}
 
     @Test(enabled=true, groups="fast")
@@ -170,7 +228,7 @@ public class TestDefaultEntitlementBillingApi {
 		PlanPhase nextPhase = nextPlan.getAllPhases()[1];
 		PriceList nextPriceList = catalogService.getFullCatalog().findPriceList(PriceListSet.DEFAULT_PRICELIST_NAME, now);
 		SubscriptionEventTransition t = new SubscriptionTransitionData(
-				zeroId, oneId, twoId, EventType.API_USER, ApiEventType.CREATE, then, now, null, null, null, null, SubscriptionState.ACTIVE, nextPlan, nextPhase, nextPriceList, 1, null, true);
+				eventId, subId, bunId, EventType.API_USER, ApiEventType.CREATE, then, now, null, null, null, null, SubscriptionState.ACTIVE, nextPlan, nextPhase, nextPriceList, 1, null, true);
 		transitions.add(t);
 
 		Account account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
@@ -184,10 +242,10 @@ public class TestDefaultEntitlementBillingApi {
 
         BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
         CallContextFactory factory = new DefaultCallContextFactory(clock);
-        BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi);
+        BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi, blockCalculator);
         SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
 
-		checkFirstEvent(events, nextPlan, subscription.getStartDate().getDayOfMonth(), oneId, now, nextPhase, ApiEventType.CREATE.toString());
+		checkFirstEvent(events, nextPlan, subscription.getStartDate().getDayOfMonth(), subId, now, nextPhase, ApiEventType.CREATE.toString());
 	}
 
     @Test(enabled=true, groups="fast")
@@ -198,7 +256,7 @@ public class TestDefaultEntitlementBillingApi {
 		PlanPhase nextPhase = nextPlan.getAllPhases()[1];
         PriceList nextPriceList = catalogService.getFullCatalog().findPriceList(PriceListSet.DEFAULT_PRICELIST_NAME, now);
 		SubscriptionEventTransition t = new SubscriptionTransitionData(
-				zeroId, oneId, twoId, EventType.API_USER, ApiEventType.CREATE, then, now, null, null, null, null, SubscriptionState.ACTIVE, nextPlan, nextPhase, nextPriceList, 1, null, true);
+				eventId, subId, bunId, EventType.API_USER, ApiEventType.CREATE, then, now, null, null, null, null, SubscriptionState.ACTIVE, nextPlan, nextPhase, nextPriceList, 1, null, true);
 		transitions.add(t);
 
         AccountUserApi accountApi = BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class);
@@ -211,10 +269,10 @@ public class TestDefaultEntitlementBillingApi {
         
         BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
         CallContextFactory factory = new DefaultCallContextFactory(clock);
-        BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi);
+        BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi, blockCalculator);
         SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
 
-		checkFirstEvent(events, nextPlan, 32, oneId, now, nextPhase, ApiEventType.CREATE.toString());
+		checkFirstEvent(events, nextPlan, 32, subId, now, nextPhase, ApiEventType.CREATE.toString());
 	}
 
     @Test(enabled=true, groups="fast")
@@ -225,7 +283,7 @@ public class TestDefaultEntitlementBillingApi {
 		PlanPhase nextPhase = nextPlan.getAllPhases()[0];
         PriceList nextPriceList = catalogService.getFullCatalog().findPriceList(PriceListSet.DEFAULT_PRICELIST_NAME, now);
 		SubscriptionEventTransition t = new SubscriptionTransitionData(
-				zeroId, oneId, twoId, EventType.API_USER, ApiEventType.CREATE, then, now, null, null, null, null, SubscriptionState.ACTIVE, nextPlan, nextPhase, nextPriceList, 1, null, true);
+				eventId, subId, bunId, EventType.API_USER, ApiEventType.CREATE, then, now, null, null, null, null, SubscriptionState.ACTIVE, nextPlan, nextPhase, nextPriceList, 1, null, true);
 		transitions.add(t);
 
 		Account account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
@@ -239,26 +297,96 @@ public class TestDefaultEntitlementBillingApi {
         
         BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
         CallContextFactory factory = new DefaultCallContextFactory(clock);
-        BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi);
+        BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi, blockCalculator);
         SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
 
-		checkFirstEvent(events, nextPlan, subscription.getStartDate().plusDays(30).getDayOfMonth(), oneId, now, nextPhase, ApiEventType.CREATE.toString());
+		checkFirstEvent(events, nextPlan, subscription.getStartDate().plusDays(30).getDayOfMonth(), subId, now, nextPhase, ApiEventType.CREATE.toString());
 	}
 
+    @Test(enabled=true, groups="fast")
+    public void testBillingEventsWithBlock() throws CatalogApiException {
+        DateTime now = clock.getUTCNow();
+        DateTime then = now.minusDays(1);
+        Plan nextPlan = catalogService.getFullCatalog().findPlan("PickupTrialEvergreen10USD", now);
+        PlanPhase nextPhase = nextPlan.getAllPhases()[1];
+        PriceList nextPriceList = catalogService.getFullCatalog().findPriceList(PriceListSet.DEFAULT_PRICELIST_NAME, now);
+        SubscriptionEventTransition t = new SubscriptionTransitionData(
+                eventId, subId, bunId, EventType.API_USER, ApiEventType.CREATE, then, now, null, null, null, null, SubscriptionState.ACTIVE, nextPlan, nextPhase, nextPriceList, 1, null, true);
+        transitions.add(t);
+
+        AccountUserApi accountApi = BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class);
+        Account account = BrainDeadProxyFactory.createBrainDeadProxyFor(Account.class);
+        ((ZombieControl)account).addResult("getBillCycleDay", 32);
+        ((ZombieControl)account).addResult("getCurrency", Currency.USD);
+        ((ZombieControl)accountApi).addResult("getAccountById", account);
+        ((ZombieControl)account).addResult("getId", UUID.randomUUID());
+
+        ((MockCatalog)catalogService.getFullCatalog()).setBillingAlignment(BillingAlignment.ACCOUNT);
+        
+        final SortedSet<BlockingState> blockingStates = new TreeSet<BlockingState>();
+        blockingStates.add(new DefaultBlockingState(bunId,DISABLED_BUNDLE, Blockable.Type.SUBSCRIPTION_BUNDLE, "test", true, true, true, now.plusDays(1)));
+        blockingStates.add(new DefaultBlockingState(bunId,CLEAR_BUNDLE, Blockable.Type.SUBSCRIPTION_BUNDLE, "test", false, false, false, now.plusDays(2)));
+        
+        BlockingCalculator blockingCal = new BlockingCalculator(new BlockingApi() {
+            
+            @Override
+            public <T extends Blockable> void setBlockingState(BlockingState state) {}
+            
+            @Override
+            public BlockingState getBlockingStateFor(UUID overdueableId, Type type) {
+                return null;
+            }
+            
+            @Override
+            public BlockingState getBlockingStateFor(Blockable overdueable) {
+                return null;
+            }
+            
+            @Override
+            public SortedSet<BlockingState> getBlockingHistory(UUID overdueableId, Type type) {
+                if(type == Type.SUBSCRIPTION_BUNDLE) {
+                    return blockingStates;
+                }
+                return new TreeSet<BlockingState>();
+            }
+            
+            @Override
+            public SortedSet<BlockingState> getBlockingHistory(Blockable overdueable) {
+                return new TreeSet<BlockingState>();
+            }
+        });
+        
+        BillCycleDayCalculator bcdCalculator = new BillCycleDayCalculator(catalogService, entitlementApi);
+        CallContextFactory factory = new DefaultCallContextFactory(clock);
+        BillingApi api = new DefaultBillingApi(null, factory, accountApi, bcdCalculator, entitlementApi, blockingCal);
+        SortedSet<BillingEvent> events = api.getBillingEventsForAccountAndUpdateAccountBCD(new UUID(0L,0L));
+
+        Assert.assertEquals(events.size(), 3);
+        Iterator<BillingEvent> it = events.iterator();
+       
+        checkEvent(it.next(), nextPlan, 32, subId, now, nextPhase, ApiEventType.CREATE.toString(), nextPhase.getFixedPrice(), nextPhase.getRecurringPrice());
+        checkEvent(it.next(), nextPlan, 32, subId, now.plusDays(1), nextPhase, ApiEventType.CANCEL.toString(), new MockPrice("0"), new MockPrice("0"));
+        checkEvent(it.next(), nextPlan, 32, subId, now.plusDays(2), nextPhase, ApiEventType.RE_CREATE.toString(), nextPhase.getFixedPrice(), nextPhase.getRecurringPrice());
+        
+    }
 
 	private void checkFirstEvent(SortedSet<BillingEvent> events, Plan nextPlan,
 			int BCD, UUID id, DateTime time, PlanPhase nextPhase, String desc) throws CatalogApiException {
 		Assert.assertEquals(events.size(), 1);
-		BillingEvent event = events.first();
+		checkEvent(events.first(), nextPlan,
+	            BCD, id, time, nextPhase, desc, nextPhase.getFixedPrice(), nextPhase.getRecurringPrice());
+	}
 
-        if(nextPhase.getFixedPrice() != null) {
-			Assert.assertEquals(nextPhase.getFixedPrice().getPrice(Currency.USD), event.getFixedPrice());
+	private void checkEvent(BillingEvent event, Plan nextPlan,
+	            int BCD, UUID id, DateTime time, PlanPhase nextPhase, String desc, InternationalPrice fixedPrice, InternationalPrice recurringPrice) throws CatalogApiException {
+        if(fixedPrice != null) {
+			Assert.assertEquals(fixedPrice.getPrice(Currency.USD), event.getFixedPrice());
         } else {
             assertNull(event.getFixedPrice());
 		}
 
-		if(nextPhase.getRecurringPrice() != null) {
-			Assert.assertEquals(nextPhase.getRecurringPrice().getPrice(Currency.USD), event.getRecurringPrice());
+		if(recurringPrice != null) {
+			Assert.assertEquals(recurringPrice.getPrice(Currency.USD), event.getRecurringPrice());
         } else {
             assertNull(event.getRecurringPrice());
 		}
@@ -270,7 +398,7 @@ public class TestDefaultEntitlementBillingApi {
 		Assert.assertEquals(nextPlan, event.getPlan());
 		Assert.assertEquals(nextPhase.getBillingPeriod(), event.getBillingPeriod());
 		Assert.assertEquals(BillingModeType.IN_ADVANCE, event.getBillingMode());
-		Assert.assertEquals(desc, event.getDescription());
+		Assert.assertEquals(desc, event.getTransitionType().toString());
 	}
 
 
diff --git a/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java b/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java
index ef4ec4f..06acac9 100644
--- a/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java
+++ b/overdue/src/main/java/com/ning/billing/ovedue/notification/DefaultOverdueCheckNotifier.java
@@ -24,14 +24,14 @@ import org.slf4j.LoggerFactory;
 
 import com.google.inject.Inject;
 import com.ning.billing.config.NotificationConfig;
-import com.ning.billing.ovedue.OverdueProperties;
+import com.ning.billing.overdue.OverdueProperties;
 import com.ning.billing.overdue.service.DefaultOverdueService;
 import com.ning.billing.util.notificationq.NotificationQueue;
 import com.ning.billing.util.notificationq.NotificationQueueService;
 import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueAlreadyExists;
 import com.ning.billing.util.notificationq.NotificationQueueService.NotificationQueueHandler;
 
-public class DefaultOverdueCheckNotifier implements  OverdueCheckNotifier {
+public class DefaultOverdueCheckNotifier implements  OverdueCheckNotifier { 
 
     private final static Logger log = LoggerFactory.getLogger(DefaultOverdueCheckNotifier.class);
 
diff --git a/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java b/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
index f809788..68c5be2 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/applicator/OverdueStateApplicator.java
@@ -23,7 +23,7 @@ import com.google.inject.Inject;
 import com.ning.billing.ErrorCode;
 import com.ning.billing.junction.api.Blockable;
 import com.ning.billing.junction.api.BlockingApi;
-import com.ning.billing.junction.api.BlockingState;
+import com.ning.billing.junction.api.blocking.DefaultBlockingState;
 import com.ning.billing.overdue.OverdueService;
 import com.ning.billing.overdue.OverdueState;
 import com.ning.billing.overdue.config.api.OverdueError;
@@ -60,7 +60,7 @@ public class OverdueStateApplicator<T extends Blockable>{
 
     protected void storeNewState(T blockable, OverdueState<T> nextOverdueState) throws OverdueError {
         try {
-            blockingApi.setBlockingState(new BlockingState(blockable.getId(), nextOverdueState.getName(), Blockable.Type.get(blockable), 
+            blockingApi.setBlockingState(new DefaultBlockingState(blockable.getId(), nextOverdueState.getName(), Blockable.Type.get(blockable), 
                     OverdueService.OVERDUE_SERVICE_NAME, blockChanges(nextOverdueState), blockEntitlement(nextOverdueState), blockBilling(nextOverdueState)));
         } catch (Exception e) {
             throw new OverdueError(e, ErrorCode.OVERDUE_CAT_ERROR_ENCOUNTERED, blockable.getId(), blockable.getClass().getName());
diff --git a/overdue/src/main/java/com/ning/billing/overdue/glue/OverdueModule.java b/overdue/src/main/java/com/ning/billing/overdue/glue/OverdueModule.java
index 8b0b15e..da54c7b 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/glue/OverdueModule.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/glue/OverdueModule.java
@@ -19,7 +19,7 @@ package com.ning.billing.overdue.glue;
 import org.skife.config.ConfigurationObjectFactory;
 
 import com.google.inject.AbstractModule;
-import com.ning.billing.ovedue.OverdueProperties;
+import com.ning.billing.overdue.OverdueProperties;
 
 
 public class OverdueModule extends AbstractModule {
diff --git a/overdue/src/main/java/com/ning/billing/overdue/service/DefaultOverdueService.java b/overdue/src/main/java/com/ning/billing/overdue/service/DefaultOverdueService.java
index e405fcc..3153f0e 100644
--- a/overdue/src/main/java/com/ning/billing/overdue/service/DefaultOverdueService.java
+++ b/overdue/src/main/java/com/ning/billing/overdue/service/DefaultOverdueService.java
@@ -21,7 +21,7 @@ import java.net.URI;
 import com.google.inject.Inject;
 import com.ning.billing.lifecycle.LifecycleHandlerType;
 import com.ning.billing.lifecycle.LifecycleHandlerType.LifecycleLevel;
-import com.ning.billing.ovedue.OverdueProperties;
+import com.ning.billing.overdue.OverdueProperties;
 import com.ning.billing.overdue.OverdueUserApi;
 import com.ning.billing.overdue.config.OverdueConfig;
 import com.ning.billing.util.config.XMLLoader;
diff --git a/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java b/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java
index e98e9b1..8d89999 100644
--- a/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java
+++ b/overdue/src/test/java/com/ning/billing/overdue/notification/TestOverdueCheckNotifier.java
@@ -53,11 +53,12 @@ import com.ning.billing.junction.plumbing.billing.DefaultBillingApi;
 import com.ning.billing.lifecycle.KillbillService.ServiceException;
 import com.ning.billing.mock.BrainDeadProxyFactory;
 import com.ning.billing.mock.BrainDeadProxyFactory.ZombieControl;
-import com.ning.billing.ovedue.OverdueProperties;
+import com.ning.billing.mock.glue.MockJunctionModule;
 import com.ning.billing.ovedue.notification.DefaultOverdueCheckNotifier;
 import com.ning.billing.ovedue.notification.DefaultOverdueCheckPoster;
 import com.ning.billing.ovedue.notification.OverdueCheckPoster;
 import com.ning.billing.ovedue.notification.OverdueListener;
+import com.ning.billing.overdue.OverdueProperties;
 import com.ning.billing.overdue.glue.OverdueModule;
 import com.ning.billing.util.bus.Bus;
 import com.ning.billing.util.bus.InMemoryBus;
@@ -133,10 +134,9 @@ public class TestOverdueCheckNotifier {
                 bind(TagDao.class).to(AuditedTagDao.class).asEagerSingleton();
                 bind(CustomFieldDao.class).to(AuditedCustomFieldDao.class).asEagerSingleton();
                 bind(GlobalLocker.class).to(MySqlGlobalLocker.class).asEagerSingleton();
-                bind(BillingApi.class).to(DefaultBillingApi.class).asEagerSingleton();
-                bind(AccountUserApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(AccountUserApi.class));
                 bind(ChargeThruApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(ChargeThruApi.class));
                 bind(EntitlementUserApi.class).toInstance(BrainDeadProxyFactory.createBrainDeadProxyFor(EntitlementUserApi.class));
+                install(new MockJunctionModule());
             }
         });