killbill-memoizeit

Big commit containting all the changes for (1) new catalog API

1/11/2012 8:54:58 PM

Changes

catalog/pom.xml 15(+15 -0)

entitlement/pom.xml 21(+21 -0)

invoice/pom.xml 15(+15 -0)

pom.xml 14(+14 -0)

Details

diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java b/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
index 7eb9b44..3f11c0e 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
@@ -53,12 +53,7 @@ public class MockPhase implements PlanPhase
                 return BigDecimal.valueOf(price);
             }
 
-            @Override
-            public Date getEffectiveDateForExistingSubscriptons()
-            {
-                return new Date();
-            }
-        };
+         };
     }
 
     @Override
@@ -78,11 +73,6 @@ public class MockPhase implements PlanPhase
                 return BigDecimal.valueOf(price);
             }
 
-            @Override
-            public Date getEffectiveDateForExistingSubscriptons()
-            {
-                return new Date();
-            }
         };
     }
 
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java b/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
index 0e0809c..72ce7ca 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
@@ -17,10 +17,12 @@
 package com.ning.billing.analytics;
 
 import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.Product;
 
+import java.util.Date;
 import java.util.Iterator;
 
 public class MockPlan implements Plan
@@ -51,6 +53,12 @@ public class MockPlan implements Plan
     {
         return name;
     }
+    
+    @Override
+    public Date getEffectiveDateForExistingSubscriptons()
+    {
+        return new Date();
+    }
 
     @Override
     public Iterator<PlanPhase> getInitialPhaseIterator()
@@ -80,4 +88,14 @@ public class MockPlan implements Plan
 	public PlanPhase[] getAllPhases() {
 		 throw new UnsupportedOperationException();
 	}
+
+	@Override
+	public PlanPhase findPhase(String name) throws CatalogApiException {
+		 throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public boolean isRetired() {
+		return false;
+	}
 }
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockProduct.java b/analytics/src/test/java/com/ning/billing/analytics/MockProduct.java
index 27ace04..36fba0d 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockProduct.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockProduct.java
@@ -61,4 +61,9 @@ public class MockProduct implements Product
     {
         return null;
     }
+
+	@Override
+	public boolean isRetired() {
+		return false;
+	}
 }
diff --git a/api/src/main/java/com/ning/billing/catalog/api/Catalog.java b/api/src/main/java/com/ning/billing/catalog/api/Catalog.java
index 0fe2e25..3c04a74 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/Catalog.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/Catalog.java
@@ -16,45 +16,65 @@
 
 package com.ning.billing.catalog.api;
 
-import java.util.Date;
+import org.joda.time.DateTime;
 
 public interface Catalog {
+	//
+    // Simple getters
+    //
+    public abstract String getCatalogName();
 
-	public abstract Product[] getProducts();
-	
-	public abstract Plan findPlan(String productName, BillingPeriod term, String priceList) throws CatalogApiException;
+    public abstract Currency[] getSupportedCurrencies(DateTime requestedDate);
 
-	public abstract Plan findPlan(String name) throws CatalogApiException;
+	public abstract Product[] getProducts(DateTime requestedDate);
+	
+	public abstract Plan[] getPlans(DateTime requestedDate);
 
-    public abstract Product findProduct(String name) throws CatalogApiException;
+	
+	//
+	// Find a plan
+	//
 
-    public abstract PlanPhase findPhase(String name) throws CatalogApiException;
+	public abstract Plan findPlan(String name, DateTime requestedDate) throws CatalogApiException;
 
+	public abstract Plan findPlan(String productName, BillingPeriod term, String priceListName,
+									DateTime requestedDate) throws CatalogApiException;
 	
-	public abstract Currency[] getSupportedCurrencies();
-
-	public abstract Plan[] getPlans();
+	public abstract Plan findPlan(String name, DateTime effectiveDate, DateTime subscriptionStartDate) throws CatalogApiException;
 
+	public abstract Plan findPlan(String productName, BillingPeriod term, String priceListName,
+									DateTime requestedDate, DateTime subscriptionStartDate) throws CatalogApiException;
+	
+	//
+	// Find a product
+	//
+    public abstract Product findProduct(String name, DateTime requestedDate) throws CatalogApiException;
+
+    //
+    // Find a phase
+    //  
+    public abstract PlanPhase findPhase(String name, DateTime requestedDate, DateTime subscriptionStartDate) throws CatalogApiException;
+
+    //
+    // Rules
+    //
 	public abstract ActionPolicy planChangePolicy(PlanPhaseSpecifier from,
-			PlanSpecifier to) throws CatalogApiException;
+			PlanSpecifier to, DateTime requestedDate) throws CatalogApiException;
 
 	public abstract PlanChangeResult planChange(PlanPhaseSpecifier from,
-			PlanSpecifier to) throws IllegalPlanChange, CatalogApiException;
+			PlanSpecifier to, DateTime requestedDate) throws CatalogApiException;
 
-    public abstract Date getEffectiveDate();
+    public abstract ActionPolicy planCancelPolicy(PlanPhaseSpecifier planPhase, DateTime requestedDate) throws CatalogApiException;
 
-    public abstract ActionPolicy planCancelPolicy(PlanPhaseSpecifier planPhase) throws CatalogApiException;
+    public abstract PlanAlignmentCreate planCreateAlignment(PlanSpecifier specifier, DateTime requestedDate) throws CatalogApiException;
 
-    public abstract void configureEffectiveDate(Date date);
-
-    public abstract String getCatalogName();
-
-    public abstract PlanAlignmentCreate planCreateAlignment(PlanSpecifier specifier) throws CatalogApiException;
-
-    public abstract BillingAlignment billingAlignment(PlanPhaseSpecifier planPhase) throws CatalogApiException;
+    public abstract BillingAlignment billingAlignment(PlanPhaseSpecifier planPhase, DateTime requestedDate) throws CatalogApiException;
 
     public abstract PlanAlignmentChange planChangeAlignment(PlanPhaseSpecifier from,
-			PlanSpecifier to) throws CatalogApiException;
+			PlanSpecifier to, DateTime requestedDate) throws CatalogApiException;
 
+    public abstract boolean canCreatePlan(PlanSpecifier specifier, DateTime requestedDate) throws CatalogApiException;
+	
+	
 	
-}
\ No newline at end of file
+}
diff --git a/api/src/main/java/com/ning/billing/catalog/api/CatalogService.java b/api/src/main/java/com/ning/billing/catalog/api/CatalogService.java
index ab70569..c363a87 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/CatalogService.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/CatalogService.java
@@ -20,6 +20,7 @@ import com.ning.billing.lifecycle.KillbillService;
 
 public interface CatalogService extends KillbillService {
 
-	public abstract Catalog getCatalog();
+	public abstract Catalog getFullCatalog();
+	public abstract StaticCatalog getCurrentCatalog();
 
 }
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/catalog/api/InternationalPrice.java b/api/src/main/java/com/ning/billing/catalog/api/InternationalPrice.java
index 44252fb..2876f1d 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/InternationalPrice.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/InternationalPrice.java
@@ -17,7 +17,6 @@
 package com.ning.billing.catalog.api;
 
 import java.math.BigDecimal;
-import java.util.Date;
 
 
 public interface InternationalPrice {
@@ -26,6 +25,4 @@ public interface InternationalPrice {
 
 	public abstract BigDecimal getPrice(Currency currency) throws CatalogApiException;
 
-	public abstract Date getEffectiveDateForExistingSubscriptons();
-
 }
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/catalog/api/Plan.java b/api/src/main/java/com/ning/billing/catalog/api/Plan.java
index a1b6815..c0dbce5 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/Plan.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/Plan.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.catalog.api;
 
+import java.util.Date;
 import java.util.Iterator;
 
 public interface Plan {
@@ -26,6 +27,8 @@ public interface Plan {
 
 	public abstract String getName();
 
+	public abstract boolean isRetired();
+
 	public abstract Iterator<PlanPhase> getInitialPhaseIterator();
 
 	public abstract PlanPhase getFinalPhase();
@@ -35,4 +38,8 @@ public interface Plan {
 	public abstract int getPlansAllowedInBundle();
 
 	public abstract PlanPhase[] getAllPhases();
+
+	public abstract Date getEffectiveDateForExistingSubscriptons();
+
+	public abstract PlanPhase findPhase(String name) throws CatalogApiException;
 }
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/catalog/api/PriceList.java b/api/src/main/java/com/ning/billing/catalog/api/PriceList.java
index 2d7192b..58a98fa 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/PriceList.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/PriceList.java
@@ -21,6 +21,8 @@ public interface PriceList {
 
 	public abstract String getName();
 
+	public abstract boolean isRetired();
+
 	public abstract Plan findPlan(Product product, BillingPeriod period);
 
 }
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/catalog/api/Product.java b/api/src/main/java/com/ning/billing/catalog/api/Product.java
index 8483678..e226a0d 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/Product.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/Product.java
@@ -21,6 +21,8 @@ public interface Product {
 
 	public abstract String getName();
 
+	public abstract boolean isRetired();
+
 	public abstract Product[] getAvailable();
 
 	public abstract Product[] getIncluded();
@@ -29,4 +31,5 @@ public interface Product {
 
 	public abstract String getCatalogName();
 
+
 }
\ No newline at end of file
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
new file mode 100644
index 0000000..0db7db5
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/catalog/api/StaticCatalog.java
@@ -0,0 +1,76 @@
+/*
+ * 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.catalog.api;
+
+import java.util.Date;
+
+
+public interface StaticCatalog {
+    //
+    // Simple getters
+    //
+    public abstract String getCatalogName();
+    
+    public abstract Date getEffectiveDate();
+
+    public abstract Currency[] getCurrentSupportedCurrencies();
+
+	public abstract Product[] getCurrentProducts();
+	
+	public abstract Plan[] getCurrentPlans();
+	
+	//
+	// Find a plan
+	//
+	public abstract Plan findCurrentPlan(String productName, BillingPeriod term, String priceList) throws CatalogApiException;
+
+	public abstract Plan findCurrentPlan(String name) throws CatalogApiException;
+
+	//
+	// Find a product
+	//
+    public abstract Product findCurrentProduct(String name) throws CatalogApiException;
+
+    //
+    // Find a phase
+    //
+    public abstract PlanPhase findCurrentPhase(String name) throws CatalogApiException;
+    
+    //
+    // Rules
+    //
+	public abstract ActionPolicy planChangePolicy(PlanPhaseSpecifier from,
+			PlanSpecifier to) throws CatalogApiException;
+
+	public abstract PlanChangeResult planChange(PlanPhaseSpecifier from,
+			PlanSpecifier to) throws CatalogApiException;
+
+
+    public abstract ActionPolicy planCancelPolicy(PlanPhaseSpecifier planPhase) throws CatalogApiException;
+
+    public abstract PlanAlignmentCreate planCreateAlignment(PlanSpecifier specifier) throws CatalogApiException;
+
+    public abstract BillingAlignment billingAlignment(PlanPhaseSpecifier planPhase) throws CatalogApiException;
+
+    public abstract PlanAlignmentChange planChangeAlignment(PlanPhaseSpecifier from,
+			PlanSpecifier to) throws CatalogApiException;
+
+    public abstract boolean canCreatePlan(PlanSpecifier specifier) throws CatalogApiException;
+
+
+	
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/billing/BillingEvent.java b/api/src/main/java/com/ning/billing/entitlement/api/billing/BillingEvent.java
index 4d603e1..d3425bb 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/billing/BillingEvent.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/billing/BillingEvent.java
@@ -17,7 +17,6 @@
 package com.ning.billing.entitlement.api.billing;
 
 import java.math.BigDecimal;
-import java.util.UUID;
 
 import org.joda.time.DateTime;
 
@@ -25,6 +24,9 @@ import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.Currency;
 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.entitlement.api.user.Subscription;
 
 public interface BillingEvent extends Comparable<BillingEvent> {
 
@@ -38,9 +40,9 @@ public interface BillingEvent extends Comparable<BillingEvent> {
 
     /**
      *
-     * @return the id for the matching subscription
+     * @return the subscription
      */
-    public UUID getSubscriptionId();
+    public Subscription getSubscription();
 
     /**
      *
@@ -50,16 +52,16 @@ public interface BillingEvent extends Comparable<BillingEvent> {
 
     /**
      *
-     * @return the name of the plan phase
+     * @return the plan phase
      */
-    public String getPlanPhaseName();
+    public PlanPhase getPlanPhase();
 
 
     /**
      *
-     * @return the name of the plan
+     * @return the plan
      */
-    public String getPlanName();
+    public Plan getPlan();
 
     /**
      *
diff --git a/api/src/main/java/com/ning/billing/entitlement/api/billing/DefaultBillingEvent.java b/api/src/main/java/com/ning/billing/entitlement/api/billing/DefaultBillingEvent.java
index 744a339..5f64dc7 100644
--- a/api/src/main/java/com/ning/billing/entitlement/api/billing/DefaultBillingEvent.java
+++ b/api/src/main/java/com/ning/billing/entitlement/api/billing/DefaultBillingEvent.java
@@ -25,26 +25,29 @@ import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.Currency;
 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.entitlement.api.user.Subscription;
 import com.ning.billing.entitlement.api.user.SubscriptionTransition;
 
 public class DefaultBillingEvent implements BillingEvent {
     final private int billCycleDay;
-    final private UUID subscriptionId;
+    final private Subscription subscription;
     final private DateTime effectiveDate;
-    final private String planPhaseName;
-    final private String planName;
+    final private PlanPhase planPhase;
+    final private Plan plan;
     final private InternationalPrice fixedPrice;
     final private InternationalPrice recurringPrice;
     final private String description;
     final private BillingModeType billingModeType;
     final private BillingPeriod billingPeriod;
     
-    public DefaultBillingEvent(SubscriptionTransition transition, int billCycleDay) {
+    public DefaultBillingEvent(SubscriptionTransition transition, Subscription subscription, int billCycleDay) {
         this.billCycleDay = billCycleDay;
-        subscriptionId = transition.getSubscriptionId();
+        this.subscription = subscription;
         effectiveDate = transition.getEffectiveTransitionTime();
-        planPhaseName = transition.getNextPhase().getName();
-        planName = transition.getNextPlan().getName();
+        planPhase = transition.getNextPhase();
+        plan = transition.getNextPlan();
         fixedPrice = transition.getNextPhase().getFixedPrice();
         recurringPrice = transition.getNextPhase().getRecurringPrice();
         description = transition.getTransitionType().toString();
@@ -54,12 +57,12 @@ public class DefaultBillingEvent implements BillingEvent {
     }
 
     // Intended for test only
-    public DefaultBillingEvent(UUID subscriptionId, DateTime effectiveDate, String planName, String planPhaseName, InternationalPrice fixedPrice,
+    public DefaultBillingEvent(Subscription subscription, DateTime effectiveDate, Plan plan, PlanPhase planPhase, InternationalPrice fixedPrice,
             InternationalPrice recurringPrice, BillingPeriod billingPeriod, int billCycleDay, BillingModeType billingModeType, String description) {
-        this.subscriptionId = subscriptionId;
+        this.subscription = subscription;
         this.effectiveDate = effectiveDate;
-        this.planName = planName;
-        this.planPhaseName = planPhaseName;
+        this.plan = plan;
+        this.planPhase = planPhase;
         this.fixedPrice = fixedPrice;
         this.recurringPrice = recurringPrice;
         this.billingPeriod = billingPeriod;
@@ -70,14 +73,14 @@ public class DefaultBillingEvent implements BillingEvent {
 
     @Override
     public int compareTo(BillingEvent e1) {
-        if (getSubscriptionId().equals(e1.getSubscriptionId())) {
+        if (getSubscription().getId().equals(e1.getSubscription().getId())) {
             if (getEffectiveDate().equals(e1.getEffectiveDate())) { //ordering with a HashSet fails if we get equality
                 return hashCode() - e1.hashCode();
             } else {
                 return getEffectiveDate().compareTo(e1.getEffectiveDate());
             }
         } else {
-            return getSubscriptionId().compareTo(e1.getSubscriptionId());
+            return getSubscription().getId().compareTo(e1.getSubscription().getId());
         }
     }
 
@@ -87,8 +90,8 @@ public class DefaultBillingEvent implements BillingEvent {
     }
 
     @Override
-    public UUID getSubscriptionId() {
-        return subscriptionId;
+    public Subscription getSubscription() {
+        return subscription;
     }
 
     @Override
@@ -97,13 +100,13 @@ public class DefaultBillingEvent implements BillingEvent {
     }
 
     @Override
-    public String getPlanPhaseName() {
-        return planPhaseName;
+    public PlanPhase getPlanPhase() {
+        return planPhase;
     }
 
     @Override
-    public String getPlanName() {
-        return planName;
+    public Plan getPlan() {
+        return plan;
     }
 
     @Override
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index 8336ddb..cdf2c77 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -67,7 +67,8 @@ public enum ErrorCode {
 
     /* Price value explicitly set to NULL meaning there is no price available in that currency */
     CAT_PRICE_VALUE_NULL_FOR_CURRENCY(2011, "The value for the currency '%s' is NULL. This plan cannot be bought in this currnency."),
-
+    CAT_NULL_PRICE_LIST_NAME(2012,"Price list name was null"),
+    CAT_PRICE_LIST_NOT_FOUND(2013, "Could not find a pricelist with name '%s'"),
     /*
      * Plans
      */
@@ -77,14 +78,27 @@ public enum ErrorCode {
     /*
      * Products
      */
-    CAT_NO_SUCH_PRODUCT(2030,"Could not find any plans named '%s'"),
-
+    CAT_NO_SUCH_PRODUCT(2030,"Could not find any product named '%s'"),
+    CAT_NULL_PRODUCT_NAME(2031,"Product name was null"),
     /*
      * Phases
      */
-    CAT_NO_SUCH_PHASE(2040,"Could not find any phases named '%s'")
-    ;
+    CAT_NO_SUCH_PHASE(2040,"Could not find any phases named '%s'"),
+    CAT_BAD_PHASE_NAME(2041,"Bad phase name '%s'"),
 
+    /*
+     * Versioned Catalog
+     */
+    CAT_NO_CATALOG_FOR_GIVEN_DATE(2050, "There is no catalog version that applies for the given date '%s'"),
+    CAT_NO_CATALOG_ENTRIES_FOR_GIVEN_DATE(2051, "The are no catalog entries that apply for the given date '%s'"),
+    CAT_CATALOG_NAME_MISMATCH(2052, "The catalog name '%s' does not match the name of the catalog we are trying to add '%s'"),
+    
+    /*
+     * Billing Alignment
+     */
+    CAT_INVALID_BILLING_ALIGNMENT(2060, "Invalid billing alignment '%s'")
+    
+    ;
     private int code;
     private String format;
 

catalog/pom.xml 15(+15 -0)

diff --git a/catalog/pom.xml b/catalog/pom.xml
index 8d5c9c1..3d69bd5 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -43,4 +43,19 @@
             <scope>provided</scope>
         </dependency>
     </dependencies>
+     <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
 </project>
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java
index 813ed2b..7f88f07 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultCatalogService.java
@@ -20,6 +20,7 @@ import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.ning.billing.catalog.api.Catalog;
 import com.ning.billing.catalog.api.CatalogService;
+import com.ning.billing.catalog.api.StaticCatalog;
 import com.ning.billing.catalog.io.VersionedCatalogLoader;
 import com.ning.billing.config.CatalogConfig;
 import com.ning.billing.lifecycle.KillbillService;
@@ -30,7 +31,7 @@ public class DefaultCatalogService implements KillbillService, Provider<Catalog>
 
     private static final String CATALOG_SERVICE_NAME = "catalog-service";
 
-    private static Catalog catalog;
+    private static VersionedCatalog catalog;
 
     private final CatalogConfig config;
     private boolean isInitialized;
@@ -74,7 +75,7 @@ public class DefaultCatalogService implements KillbillService, Provider<Catalog>
      * @see com.ning.billing.catalog.ICatlogService#getCatalog()
      */
     @Override
-    public Catalog getCatalog() {
+    public Catalog getFullCatalog() {
         return catalog;
     }
 
@@ -85,4 +86,9 @@ public class DefaultCatalogService implements KillbillService, Provider<Catalog>
         return catalog;
     }
 
+	@Override
+	public StaticCatalog getCurrentCatalog() {
+		return catalog;
+	}
+
 }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java
index b53dcd3..6990d3c 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultInternationalPrice.java
@@ -16,26 +16,25 @@
 
 package com.ning.billing.catalog;
 
-import com.ning.billing.ErrorCode;
-import com.ning.billing.catalog.api.*;
-import com.ning.billing.util.config.ValidatingConfig;
-import com.ning.billing.util.config.ValidationError;
-import com.ning.billing.util.config.ValidationErrors;
+import java.math.BigDecimal;
+import java.net.URI;
 
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
-import java.math.BigDecimal;
-import java.net.URI;
-import java.util.Date;
+
+import com.ning.billing.ErrorCode;
+import com.ning.billing.catalog.api.CatalogApiException;
+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.Price;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
 public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalog> implements InternationalPrice {
 
-	//TODO MDW Validation - effectiveDateForExistingSubscriptons > catalog effectiveDate 
-	@XmlElement(required=false)
-	private Date effectiveDateForExistingSubscriptons;
-
 	//TODO: Must have a price point for every configured currency
 	//TODO: No prices is a zero cost plan
 	@XmlElement(name="price")
@@ -50,13 +49,7 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
 		return prices;
 	}
 
-	/* (non-Javadoc)
-	 * @see com.ning.billing.catalog.IInternationalPrice#getEffectiveDateForExistingSubscriptons()
-	 */
-	@Override
-	public Date getEffectiveDateForExistingSubscriptons() {
-		return effectiveDateForExistingSubscriptons;
-	}
+
 
 	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IInternationalPrice#getPrice(com.ning.billing.catalog.api.Currency)
@@ -71,12 +64,6 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
 		throw new CatalogApiException(ErrorCode.CAT_NO_PRICE_FOR_CURRENCY, currency);
 	}
 
-
-	protected void setEffectiveDateForExistingSubscriptons(
-			Date effectiveDateForExistingSubscriptons) {
-		this.effectiveDateForExistingSubscriptons = effectiveDateForExistingSubscriptons;
-	}
-
 	protected DefaultInternationalPrice setPrices(DefaultPrice[] prices) {
 		this.prices = prices;
 		return this;
@@ -85,7 +72,7 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
 
 	@Override
 	public ValidationErrors validate(StandaloneCatalog catalog, ValidationErrors errors)  {
-		Currency[] supportedCurrencies = catalog.getSupportedCurrencies();
+		Currency[] supportedCurrencies = catalog.getCurrentSupportedCurrencies();
 		for (Price p : prices) {
 			Currency currency = p.getCurrency();
 			if(!currencyIsSupported(currency, supportedCurrencies)) {
@@ -99,14 +86,6 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
 				// No currency => nothing to check, ignore exception
 			}
 		}
-		if(effectiveDateForExistingSubscriptons != null &&
-				catalog.getEffectiveDate().getTime() > effectiveDateForExistingSubscriptons.getTime()) {
-			errors.add(new ValidationError(String.format("Price effective date %s is before catalog effective date '%s'",
-					effectiveDateForExistingSubscriptons,
-					catalog.getEffectiveDate().getTime()), 
-					catalog.getCatalogURI(), DefaultInternationalPrice.class, ""));
-		}
-		
 		return errors;
 	}
 	
@@ -129,7 +108,7 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
 	}
 
 	private synchronized DefaultPrice[] getZeroPrice(StandaloneCatalog root) {
-		Currency[] currencies = root.getSupportedCurrencies();
+		Currency[] currencies = root.getCurrentSupportedCurrencies();
 		DefaultPrice[] zeroPrice = new DefaultPrice[currencies.length];
 		for(int i = 0; i < currencies.length; i++) {
 			zeroPrice[i] = new DefaultPrice();
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java
index 3620162..4972e26 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlan.java
@@ -16,25 +16,42 @@
 
 package com.ning.billing.catalog;
 
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Iterator;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlID;
+import javax.xml.bind.annotation.XmlIDREF;
+
+import com.ning.billing.ErrorCode;
 import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.Plan;
 import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.Product;
 import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationError;
 import com.ning.billing.util.config.ValidationErrors;
 
-import javax.xml.bind.annotation.*;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Iterator;
-
 @XmlAccessorType(XmlAccessType.NONE)
 public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements Plan {
 
-
 	@XmlAttribute(required=true)
 	@XmlID
 	private String name;
+	
+	@XmlAttribute(required=false)
+	private Boolean retired = false;
+	
+	//TODO MDW Validation - effectiveDateForExistingSubscriptons > catalog effectiveDate 
+	@XmlElement(required=false)
+	private Date effectiveDateForExistingSubscriptons;
 
 	@XmlElement(required=true)
 	@XmlIDREF
@@ -55,6 +72,12 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
 	private Integer plansAllowedInBundle = 1;
 
 	/* (non-Javadoc)
+	 * @see com.ning.billing.catalog.IPlan#getEffectiveDateForExistingSubscriptons()
+	 */
+	@Override
+	public Date getEffectiveDateForExistingSubscriptons() {
+		return effectiveDateForExistingSubscriptons;
+	}	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IPlan#getPhases()
 	 */
     @Override
@@ -77,6 +100,12 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
 	public String getName() {
 		return name;
 	}
+	
+	@Override
+	public boolean isRetired() {
+		return retired;
+	}
+	
 	@Override
 	public DefaultPlanPhase getFinalPhase() {
 		return finalPhase;
@@ -97,6 +126,17 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
 	}
 
 	@Override
+	public PlanPhase findPhase(String name) throws CatalogApiException {
+		for(PlanPhase pp : getAllPhases()) {
+			if(pp.getName().equals(name)) {
+				return pp;
+			}
+
+		}
+		throw new CatalogApiException(ErrorCode.CAT_NO_SUCH_PHASE, name);
+	}
+
+	@Override
 	public BillingPeriod getBillingPeriod(){
 		return finalPhase.getBillingPeriod();
 	}
@@ -138,9 +178,21 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
 
 	@Override
 	public ValidationErrors validate(StandaloneCatalog catalog, ValidationErrors errors) {
+		if(effectiveDateForExistingSubscriptons != null &&
+				catalog.getEffectiveDate().getTime() > effectiveDateForExistingSubscriptons.getTime()) {
+			errors.add(new ValidationError(String.format("Price effective date %s is before catalog effective date '%s'",
+					effectiveDateForExistingSubscriptons,
+					catalog.getEffectiveDate().getTime()), 
+					catalog.getCatalogURI(), DefaultInternationalPrice.class, ""));
+		}
+		
 		return errors;
 	}
 
+	protected void setEffectiveDateForExistingSubscriptons(
+			Date effectiveDateForExistingSubscriptons) {
+		this.effectiveDateForExistingSubscriptons = effectiveDateForExistingSubscriptons;
+	}
 
 	protected DefaultPlan setName(String name) {
 		this.name = name;
@@ -166,4 +218,16 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
 		this.initialPhases = phases;
 		return this;
 	}
+
+	public DefaultPlan setRetired(boolean retired) {
+		this.retired = retired;
+		return this;
+	}
+	
+	public DefaultPlan setPlansAllowedInBundle(Integer plansAllowedInBundle) {
+		this.plansAllowedInBundle = plansAllowedInBundle;
+		return this;
+	}
+	
+	
 }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java
index e086bfe..4afe278 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPlanPhase.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.catalog;
 
+import com.ning.billing.ErrorCode;
 import com.ning.billing.catalog.api.*;
 import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationError;
@@ -51,6 +52,20 @@ public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implem
 
 	//Not exposed in XML
 	private Plan plan;
+	
+	public static String phaseName(Plan plan, PlanPhase phase) {
+		return plan.getName() + "-" + phase.getPhaseType().toString().toLowerCase();
+	}
+	
+	public static String planName(String phaseName) throws CatalogApiException {
+		for(PhaseType type : PhaseType.values()) {
+			if(phaseName.endsWith(type.toString().toLowerCase())) {
+				return phaseName.substring(0, phaseName.length() - type.toString().length() - 1);
+			}
+		}
+		throw new CatalogApiException(ErrorCode.CAT_BAD_PHASE_NAME, phaseName);
+	}
+
 
 	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IPlanPhase#getRecurringPrice()
@@ -89,7 +104,7 @@ public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implem
 	 */
 	@Override
 	public String getName() {
-		return plan.getName() + "-" + type.toString().toLowerCase();
+		return phaseName(plan,this);
 	}
 
 	/* (non-Javadoc)
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceList.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceList.java
index 04916ba..48de5d4 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceList.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceList.java
@@ -32,6 +32,9 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
 	@XmlID
 	private String name;
 
+	@XmlAttribute(required=false)
+	private Boolean retired = false;
+	
 	@XmlElementWrapper(name="plans", required=true)
 	@XmlElement(name="plan", required=true)
 	@XmlIDREF
@@ -47,6 +50,10 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
 	protected DefaultPlan[] getPlans() {
 		return plans;
 	}
+
+	public boolean isRetired() {
+		return retired;
+	}
 	
 	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IPriceList#getName()
@@ -94,6 +101,11 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
         }
         return count;
     }
+	
+	public DefaultPriceList setRetired(boolean retired) {
+		this.retired = retired;
+		return this;
+	}
 
 
 }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceListSet.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceListSet.java
index b876fa9..f0636dd 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceListSet.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultPriceListSet.java
@@ -16,17 +16,19 @@
 
 package com.ning.billing.catalog;
 
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+import com.ning.billing.ErrorCode;
 import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.PriceListSet;
 import com.ning.billing.catalog.api.Product;
 import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationError;
 import com.ning.billing.util.config.ValidationErrors;
 
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-
 @XmlAccessorType(XmlAccessType.NONE)
 public class DefaultPriceListSet extends ValidatingConfig<StandaloneCatalog> {
 	@XmlElement(required=true, name="defaultPriceList")
@@ -47,7 +49,7 @@ public class DefaultPriceListSet extends ValidatingConfig<StandaloneCatalog> {
 	}
 
 	public DefaultPlan getPlanListFrom(String priceListName, Product product,
-			BillingPeriod period) {
+			BillingPeriod period) throws CatalogApiException {
 		DefaultPlan result = null;
 		DefaultPriceList pl = findPriceListFrom(priceListName);
 		if(pl != null) {
@@ -60,7 +62,10 @@ public class DefaultPriceListSet extends ValidatingConfig<StandaloneCatalog> {
 		return defaultPricelist.findPlan(product, period);
 	}
 
-	public DefaultPriceList findPriceListFrom (String priceListName) {
+	public DefaultPriceList findPriceListFrom (String priceListName) throws CatalogApiException {
+		if(priceListName == null) {
+			throw new CatalogApiException(ErrorCode.CAT_NULL_PRICE_LIST_NAME);
+		}
 		if (defaultPricelist.getName().equals(priceListName)) {
 			return defaultPricelist;
 		} 
@@ -69,7 +74,7 @@ public class DefaultPriceListSet extends ValidatingConfig<StandaloneCatalog> {
 				return pl;
 			}
 		}
-		return null;
+		throw new CatalogApiException(ErrorCode.CAT_PRICE_LIST_NOT_FOUND, priceListName);
 	}
 
 	@Override
diff --git a/catalog/src/main/java/com/ning/billing/catalog/DefaultProduct.java b/catalog/src/main/java/com/ning/billing/catalog/DefaultProduct.java
index 79520ce..bf8cfd4 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/DefaultProduct.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/DefaultProduct.java
@@ -22,6 +22,7 @@ import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationErrors;
 
 import javax.xml.bind.annotation.*;
+
 import java.net.URI;
 
 @XmlAccessorType(XmlAccessType.NONE)
@@ -32,6 +33,9 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
 	@XmlID
     private String name;
 
+	@XmlAttribute(required=false)
+	private Boolean retired = false;
+	
 	@XmlElement(required=true)
     private ProductCategory category;
 	
@@ -53,6 +57,11 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
 	}
 
 	@Override
+	public boolean isRetired() {
+		return retired;
+	}
+	
+	@Override
     public ProductCategory getCategory() {
 		return category;
 	}
@@ -140,4 +149,9 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
 		return this;
 	}
 
+	public DefaultProduct setRetired(boolean retired) {
+		this.retired = retired;
+		return this;
+	}
+
 }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java b/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
index 4ad78df..7ef0600 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
@@ -60,13 +60,11 @@ public class VersionedCatalogLoader implements ICatalogLoader  {
 				xmlURIs = findXmlReferences(directoryContents, new URL(uriString));
 			}
 			
-			VersionedCatalog result = new VersionedCatalog();
+			VersionedCatalog result = new VersionedCatalog(clock);
 			for(URI u : xmlURIs) {
 				StandaloneCatalog catalog = XMLLoader.getObjectFromUri(u, StandaloneCatalog.class);
 				result.add(catalog);
 			}
-			Date now = clock.getUTCNow().toDate();
-			result.configureEffectiveDate(now);
 			return result;
 		} catch (Exception e) {
 			throw new ServiceException("Problem encountered loading catalog", e);
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/Case.java b/catalog/src/main/java/com/ning/billing/catalog/rules/Case.java
index 00bc275..7ae442f 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/Case.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/Case.java
@@ -47,10 +47,10 @@ public abstract class Case<T> extends ValidatingConfig<StandaloneCatalog> {
 	}
 	
 	protected boolean satisfiesCase(PlanSpecifier planPhase, StandaloneCatalog c) throws CatalogApiException {
-		return (getProduct()         == null || getProduct().equals(c.findProduct(planPhase.getProductName()))) &&
+		return (getProduct()         == null || getProduct().equals(c.findCurrentProduct(planPhase.getProductName()))) &&
 		(getProductCategory() == null || getProductCategory().equals(planPhase.getProductCategory())) &&
 		(getBillingPeriod()   == null || getBillingPeriod().equals(planPhase.getBillingPeriod())) &&
-		(getPriceList()       == null || getPriceList().equals(c.getPriceListFromName(planPhase.getPriceListName())));
+		(getPriceList()       == null || getPriceList().equals(c.findCurrentPriceList(planPhase.getPriceListName())));
 	}
 
 	public static <K> K getResult(Case<K>[] cases, PlanSpecifier planSpec, StandaloneCatalog catalog) throws CatalogApiException {
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/CaseChange.java b/catalog/src/main/java/com/ning/billing/catalog/rules/CaseChange.java
index a340fdc..f101ef1 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/CaseChange.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/CaseChange.java
@@ -68,14 +68,14 @@ public abstract class CaseChange<T>  extends ValidatingConfig<StandaloneCatalog>
 			PlanSpecifier to, StandaloneCatalog catalog) throws CatalogApiException {
 		if(	
 				(phaseType     	     == null || from.getPhaseType() == phaseType) &&
-				(fromProduct 	     == null || fromProduct.equals(catalog.findProduct(from.getProductName()))) &&
+				(fromProduct 	     == null || fromProduct.equals(catalog.findCurrentProduct(from.getProductName()))) &&
 				(fromProductCategory == null || fromProductCategory.equals(from.getProductCategory())) &&
 				(fromBillingPeriod   == null || fromBillingPeriod.equals(from.getBillingPeriod())) &&
-				(toProduct           == null || toProduct.equals(catalog.findProduct(to.getProductName()))) &&
+				(toProduct           == null || toProduct.equals(catalog.findCurrentProduct(to.getProductName()))) &&
 				(toProductCategory   == null || toProductCategory.equals(to.getProductCategory())) &&
 				(toBillingPeriod     == null || toBillingPeriod.equals(to.getBillingPeriod())) &&
-				(fromPriceList       == null || fromPriceList.equals(catalog.getPriceListFromName(from.getPriceListName()))) &&
-				(toPriceList         == null || toPriceList.equals(catalog.getPriceListFromName(to.getPriceListName())))
+				(fromPriceList       == null || fromPriceList.equals(catalog.findCurrentPriceList(from.getPriceListName()))) &&
+				(toPriceList         == null || toPriceList.equals(catalog.findCurrentPriceList(to.getPriceListName())))
 				) {
 			return getResult();
 		}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/CasePhase.java b/catalog/src/main/java/com/ning/billing/catalog/rules/CasePhase.java
index b38c1f8..ebd7561 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/CasePhase.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/CasePhase.java
@@ -31,9 +31,8 @@ public abstract class CasePhase<T> extends CaseStandardNaming<T> {
 	private PhaseType phaseType;	
 	
 	public T getResult(PlanPhaseSpecifier specifier, StandaloneCatalog c) throws CatalogApiException {
-		if ((phaseType       == null || 
-				specifier.getPhaseType() == null || specifier.getPhaseType() == phaseType) &&
-				satisfiesCase(new PlanSpecifier(specifier), c)
+		if ((phaseType       == null ||  specifier.getPhaseType() == phaseType) 
+				&& satisfiesCase(new PlanSpecifier(specifier), c)
 				) {
 			return getResult(); 
 		}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java b/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java
index 54aa5c7..c47529a 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java
@@ -16,17 +16,28 @@
 
 package com.ning.billing.catalog.rules;
 
-import com.ning.billing.catalog.DefaultPriceList;
-import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.catalog.api.*;
-import com.ning.billing.util.config.ValidatingConfig;
-import com.ning.billing.util.config.ValidationErrors;
-
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.DefaultPriceList;
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.api.ActionPolicy;
+import com.ning.billing.catalog.api.BillingAlignment;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.IllegalPlanChange;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanAlignmentChange;
+import com.ning.billing.catalog.api.PlanAlignmentCreate;
+import com.ning.billing.catalog.api.PlanChangeResult;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
+
 @XmlAccessorType(XmlAccessType.NONE)
 public class PlanRules extends ValidatingConfig<StandaloneCatalog>  {
 
@@ -67,11 +78,13 @@ public class PlanRules extends ValidatingConfig<StandaloneCatalog>  {
 	}
 
 	public PlanChangeResult planChange(PlanPhaseSpecifier from, PlanSpecifier to, StandaloneCatalog catalog) throws CatalogApiException {
-		DefaultPriceList priceList = catalog.getPriceListFromName(to.getPriceListName());
-		if( priceList== null ) {
-			priceList = findPriceList(from.toPlanSpecifier(), catalog);
-			to = new PlanSpecifier(to.getProductName(), to.getProductCategory(), to.getBillingPeriod(), priceList.getName());
-		} 
+		DefaultPriceList toPriceList;
+		if( to.getPriceListName() == null ) { // Pricelist may be null because it is unspecified this is the principal use-case
+			toPriceList = findPriceList(from.toPlanSpecifier(), catalog);
+			to = new PlanSpecifier(to.getProductName(), to.getProductCategory(), to.getBillingPeriod(), toPriceList.getName());
+		} else {
+			toPriceList = catalog.findCurrentPriceList(to.getPriceListName());
+		}
 		
 		ActionPolicy policy = getPlanChangePolicy(from, to, catalog);
 		if(policy == ActionPolicy.ILLEGAL) {
@@ -80,7 +93,7 @@ public class PlanRules extends ValidatingConfig<StandaloneCatalog>  {
 		
 		PlanAlignmentChange alignment = getPlanChangeAlignment(from, to, catalog);
 		
-		return new PlanChangeResult(priceList, policy, alignment);
+		return new PlanChangeResult(toPriceList, policy, alignment);
 	}
 	
 	public PlanAlignmentChange getPlanChangeAlignment(PlanPhaseSpecifier from,
@@ -95,6 +108,7 @@ public class PlanRules extends ValidatingConfig<StandaloneCatalog>  {
 				from.getPriceListName().equals(to.getPriceListName())) {
 			return ActionPolicy.ILLEGAL;
 		}
+		//Plan toPlan = catalog.findPlan()
 		
 		return CaseChange.getResult(changeCase, from, to, catalog); 
 	}
@@ -102,7 +116,7 @@ public class PlanRules extends ValidatingConfig<StandaloneCatalog>  {
 	private DefaultPriceList findPriceList(PlanSpecifier specifier, StandaloneCatalog catalog) throws CatalogApiException {
 		DefaultPriceList result = Case.getResult(priceListCase, specifier, catalog);
 		if (result == null) {
-			result = catalog.getPriceListFromName(specifier.getPriceListName());
+			result = catalog.findCurrentPriceList(specifier.getPriceListName());
 		}
 		return result;
 	}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java b/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java
index 06b24bb..b7f7b79 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/StandaloneCatalog.java
@@ -16,21 +16,39 @@
 
 package com.ning.billing.catalog;
 
+import java.net.URI;
+import java.util.Collection;
+import java.util.Date;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+
 import com.ning.billing.ErrorCode;
-import com.ning.billing.catalog.api.*;
+import com.ning.billing.catalog.api.ActionPolicy;
+import com.ning.billing.catalog.api.BillingAlignment;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.api.PlanAlignmentChange;
+import com.ning.billing.catalog.api.PlanAlignmentCreate;
+import com.ning.billing.catalog.api.PlanChangeResult;
+import com.ning.billing.catalog.api.PlanPhase;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.Product;
+import com.ning.billing.catalog.api.StaticCatalog;
 import com.ning.billing.catalog.rules.PlanRules;
 import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationError;
 import com.ning.billing.util.config.ValidationErrors;
 
-import javax.xml.bind.annotation.*;
-import java.net.URI;
-import java.util.Collection;
-import java.util.Date;
-
 @XmlRootElement(name="catalog")
 @XmlAccessorType(XmlAccessType.NONE)
-public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> implements Catalog {
+public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> implements StaticCatalog {
 	@XmlElement(required=true)
 	private Date effectiveDate;
 
@@ -80,18 +98,18 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 	 * @see com.ning.billing.catalog.ICatalog#getProducts()
 	 */
 	@Override
-	public DefaultProduct[] getProducts() {
+	public DefaultProduct[] getCurrentProducts() {
 		return products;
 	}
 
 
 	@Override
-	public Currency[] getSupportedCurrencies() {
+	public Currency[] getCurrentSupportedCurrencies() {
 		return supportedCurrencies;
 	}
 
 	@Override
-	public DefaultPlan[] getPlans() {
+	public DefaultPlan[] getCurrentPlans() {
 		return plans;
 	}
 
@@ -103,7 +121,7 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 		return planRules;
 	}
 	
-	public DefaultPriceList getPriceListFromName(String priceListName) {
+	public DefaultPriceList findCurrentPriceList(String priceListName) throws CatalogApiException {
 		return priceLists.findPriceListFrom(priceListName);
 	}
 	
@@ -111,29 +129,30 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 		return this.priceLists;
 	}
 
-	@Override
-	public void configureEffectiveDate(Date date) {
-		// Nothing to do here this is a method that is only implemented on VersionedCatalog
-	}
-
-
 	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.ICatalog#getPlan(java.lang.String, java.lang.String)
 	 */
 	@Override
-	public DefaultPlan findPlan(String productName, BillingPeriod period, String priceListName) throws CatalogApiException {
-		Product product = findProduct(productName);
+	public DefaultPlan findCurrentPlan(String productName, BillingPeriod period, String priceListName) throws CatalogApiException {
+		if (productName == null ) {
+			throw new CatalogApiException(ErrorCode.CAT_NULL_PRODUCT_NAME);
+		}
+		if (priceLists == null) {
+			throw new CatalogApiException(ErrorCode.CAT_PRICE_LIST_NOT_FOUND,priceListName);
+		}
+		Product product = findCurrentProduct(productName);
 		DefaultPlan result = priceLists.getPlanListFrom(priceListName, product, period);
 		if ( result == null) {
-			throw new CatalogApiException(ErrorCode.CAT_PLAN_NOT_FOUND, productName, period.toString(), priceListName);
+			String periodString = (period == null) ? "NULL" :  period.toString();
+			throw new CatalogApiException(ErrorCode.CAT_PLAN_NOT_FOUND, productName, periodString, priceListName);
 		}
 		return result;
 	}
 	
 	@Override
-	public DefaultPlan findPlan(String name) throws CatalogApiException {
-		if (name == null) {
-			return null;
+	public DefaultPlan findCurrentPlan(String name) throws CatalogApiException {
+		if (name == null || plans == null) {
+			throw new CatalogApiException(ErrorCode.CAT_NO_SUCH_PLAN, name);
 		}
 		for(DefaultPlan p : plans) {
 			if(p.getName().equals(name)) {
@@ -144,7 +163,10 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 	}
 	
 	@Override
-	public Product findProduct(String name) throws CatalogApiException {
+	public Product findCurrentProduct(String name) throws CatalogApiException {
+		if (name == null || products == null) {
+			throw new CatalogApiException(ErrorCode.CAT_NO_SUCH_PRODUCT, name);
+		}
 		for(DefaultProduct p : products) {
 			if (p.getName().equals(name)) {
 				return p;
@@ -154,24 +176,18 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 	}
 
 	@Override
-	public DefaultPlanPhase findPhase(String name) throws CatalogApiException {
-		for(DefaultPlan p : plans) {
-
-			if(p.getFinalPhase().getName().equals(name)) {
-				return p.getFinalPhase();
-			}
-			if (p.getInitialPhases() != null) {
-				for(DefaultPlanPhase pp : p.getInitialPhases()) {
-					if(pp.getName().equals(name)) {
-						return pp;
-					}
-				}
-			}
+	public PlanPhase findCurrentPhase(String name) throws CatalogApiException {
+		if (name == null || plans == null) {
+			throw new CatalogApiException(ErrorCode.CAT_NO_SUCH_PHASE, name);
 		}
-
-		throw new CatalogApiException(ErrorCode.CAT_NO_SUCH_PHASE, name);
+		
+		String  planName = DefaultPlanPhase.planName(name);
+		Plan plan = findCurrentPlan(planName);
+		return plan.findPhase(name);
 	}
 
+
+
 	//////////////////////////////////////////////////////////////////////////////
 	//
 	// RULES
@@ -220,9 +236,9 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 	private Collection<? extends ValidationError> validate(StandaloneCatalog catalog,
 			ValidationErrors errors, ValidatingConfig<StandaloneCatalog>[] configs) {
 		for(ValidatingConfig<StandaloneCatalog> config: configs) {
-
+			config.validate(catalog, errors);
 		}
-		return null;
+		return errors;
 	}
 	
 
@@ -275,6 +291,14 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 		return this;
 	}
 
-
-
+	@Override
+	public boolean canCreatePlan(PlanSpecifier specifier) throws CatalogApiException {
+		Product product = findCurrentProduct(specifier.getProductName());
+		Plan plan = findCurrentPlan(specifier.getProductName(), specifier.getBillingPeriod(), specifier.getPriceListName());
+		DefaultPriceList priceList = findCurrentPriceList(specifier.getPriceListName());
+		
+		return (!product.isRetired()) &&
+				(!plan.isRetired()) &&
+				(!priceList.isRetired());
+	}
 }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java b/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
index bb48b9b..f652347 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
@@ -28,7 +28,11 @@ import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
 
-import com.google.inject.Inject;
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.ning.billing.ErrorCode;
 import com.ning.billing.catalog.api.ActionPolicy;
 import com.ning.billing.catalog.api.BillingAlignment;
 import com.ning.billing.catalog.api.BillingPeriod;
@@ -43,40 +47,137 @@ import com.ning.billing.catalog.api.PlanPhase;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PlanSpecifier;
 import com.ning.billing.catalog.api.Product;
+import com.ning.billing.catalog.api.StaticCatalog;
+import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationErrors;
 
 
 @XmlRootElement(name="catalog")
 @XmlAccessorType(XmlAccessType.NONE)
-public class VersionedCatalog extends ValidatingConfig<StandaloneCatalog> implements Catalog {
+public class VersionedCatalog extends ValidatingConfig<StandaloneCatalog> implements Catalog, StaticCatalog {
+	private static final Logger log = LoggerFactory.getLogger(VersionedCatalog.class);
 	
-	private StandaloneCatalog currentCatalog;
+	final private Clock clock;
+	private String catalogName;
 	
 	@XmlElement(name="catalogVersion", required=true)
 	private final List<StandaloneCatalog> versions = new ArrayList<StandaloneCatalog>();
-	
-	@Inject
-	public VersionedCatalog() {
+
+	public VersionedCatalog(Clock clock) {
+		this.clock = clock;
 		StandaloneCatalog baseline = new StandaloneCatalog(new Date(0)); // init with an empty catalog may need to 
 													 // populate some empty pieces here to make validation work
-		add(baseline); 
+		try {
+			add(baseline);
+		} catch (CatalogApiException e) {
+			// This should never happen
+			log.error("This error should never happpen", e);
+		} 
 	}
-	
-	private StandaloneCatalog versionForDate(Date date) {
-		StandaloneCatalog previous = versions.get(0);
-		for(StandaloneCatalog c : versions) {
+
+	//
+	// Private methods
+	//
+	private StandaloneCatalog versionForDate(DateTime date) {
+		return versions.get(indexOfVersionForDate(date.toDate()));
+	}
+
+	private List<StandaloneCatalog> versionsBeforeDate(Date date) {
+		List<StandaloneCatalog> result = new ArrayList<StandaloneCatalog>();
+		int index = indexOfVersionForDate(date);
+		for(int i = 0; i <= index; i++) {
+			result.add(versions.get(i));
+		}
+		return result;
+	}
+
+	private int indexOfVersionForDate(Date date) {
+		for(int i = 1; i < versions.size(); i++) {
+			StandaloneCatalog c = versions.get(i);
 			if(c.getEffectiveDate().getTime() > date.getTime()) {
-				return previous;
+				return i - 1;
 			}
-			previous = c;
 		}
-		return versions.get(versions.size() - 1);
+		return versions.size() - 1;
 	}
+	
+	private class PlanRequestWrapper {
+		String name;
+		String productName;
+		BillingPeriod bp;
+		String priceListName;
+		
+		public PlanRequestWrapper(String name) {
+			super();
+			this.name = name;
+		}
 
-	public void add(StandaloneCatalog e) {
-		if(currentCatalog == null) {
-			currentCatalog = e;
+		public PlanRequestWrapper(String productName, BillingPeriod bp,
+				String priceListName) {
+			super();
+			this.productName = productName;
+			this.bp = bp;
+			this.priceListName = priceListName;
+		}
+		
+		public Plan findPlan(StandaloneCatalog catalog) throws CatalogApiException {
+			if(name != null) {
+				return catalog.findCurrentPlan(name);
+			} else {
+				return catalog.findCurrentPlan(productName, bp, priceListName);
+			}
+		}
+	}
+	
+	private Plan findPlan(PlanRequestWrapper wrapper, 
+			DateTime requestedDate,
+			DateTime subscriptionStartDate) 
+					throws CatalogApiException {
+		List<StandaloneCatalog> catalogs = versionsBeforeDate(requestedDate.toDate());
+		if(catalogs.size() == 0) {
+			throw new CatalogApiException(ErrorCode.CAT_NO_CATALOG_FOR_GIVEN_DATE, requestedDate.toDate().toString());
+		}
+		
+		for(int i = catalogs.size() - 1; i >= 0 ; i--) { // Working backwards to find the latest applicable plan
+			StandaloneCatalog c = catalogs.get(i);
+			Plan plan = null;
+			try {
+				 plan = wrapper.findPlan(c);
+			} catch (CatalogApiException e) {
+				if(e.getCode() != ErrorCode.CAT_NO_SUCH_PLAN.getCode()) {
+					throw e;
+				} else { 
+					break;
+				}
+			}
+				
+			DateTime catalogEffectiveDate = new DateTime(c.getEffectiveDate());
+			if(subscriptionStartDate.isAfter(catalogEffectiveDate)) { // Its a new subscription this plan always applies
+				return plan;
+			} else { //Its an existing subscription
+				if(plan.getEffectiveDateForExistingSubscriptons() != null) { //if it is null any change to this does not apply to existing subscriptions
+					DateTime existingSubscriptionDate = new DateTime(plan.getEffectiveDateForExistingSubscriptons());
+					if(requestedDate.isAfter(existingSubscriptionDate)){ // this plan is now applicable to existing subs
+						return plan;
+					}
+				}
+			}
+		}
+		
+		throw new CatalogApiException(ErrorCode.CAT_NO_CATALOG_FOR_GIVEN_DATE, requestedDate.toDate().toString());
+	}
+	
+	//
+	// Public methods not exposed in interface
+	//
+	public void add(StandaloneCatalog e) throws CatalogApiException {
+		if(catalogName == null) {
+			catalogName = e.getCatalogName();
+		} else {
+			if(!catalogName.equals(getCatalogName())) {
+				throw new CatalogApiException(ErrorCode.CAT_CATALOG_NAME_MISMATCH,catalogName, e.getCatalogName());
+			}
 		}
 		versions.add(e);
 		Collections.sort(versions,new Comparator<StandaloneCatalog>() {
@@ -86,61 +187,144 @@ public class VersionedCatalog extends ValidatingConfig<StandaloneCatalog> implem
 			}
 		});
 	}
-
+		
 	public Iterator<StandaloneCatalog> iterator() {
 		return versions.iterator();
 	}
-	
-	@Override
-	public void configureEffectiveDate(Date date) {
-		currentCatalog = versionForDate(date); // 
-	}
 
 	public int size() {
 		return versions.size();
 	}
 
+	//
+    // Simple getters
+    //
 	@Override
-	public DefaultProduct[] getProducts() {
-		return currentCatalog.getProducts();
+	public String getCatalogName() {
+		return catalogName;
 	}
 
 	@Override
-	public Currency[] getSupportedCurrencies() {
-		return currentCatalog.getSupportedCurrencies();
+	public DefaultProduct[] getProducts(DateTime requestedDate) {
+		return versionForDate(requestedDate).getCurrentProducts();
 	}
 
 	@Override
-	public DefaultPlan[] getPlans() {
-		return currentCatalog.getPlans();
+	public Currency[] getSupportedCurrencies(DateTime requestedDate) {
+		return versionForDate(requestedDate).getCurrentSupportedCurrencies();
 	}
 
 	@Override
-	public Date getEffectiveDate() {
-		return currentCatalog.getEffectiveDate();
+	public DefaultPlan[] getPlans(DateTime requestedDate) {
+		return versionForDate(requestedDate).getCurrentPlans();
+	}
+
+	//
+	// Find a plan
+	//
+	@Override
+	public Plan findPlan(String name, 
+			DateTime requestedDate) 
+					throws CatalogApiException {
+		return versionForDate(requestedDate).findCurrentPlan(name);
+	}
+
+	@Override
+	public Plan findPlan(String productName, 
+			BillingPeriod term,
+			String priceListName,
+			DateTime requestedDate) 
+					throws CatalogApiException {
+		return versionForDate(requestedDate).findCurrentPlan(productName, term, priceListName);
+	}
+
+	@Override
+	public Plan findPlan(String name, 
+			DateTime requestedDate,
+			DateTime subscriptionStartDate) 
+					throws CatalogApiException {
+		return findPlan(new PlanRequestWrapper(name), requestedDate, subscriptionStartDate);
+	}
+
+	@Override
+	public Plan findPlan(String productName, 
+			BillingPeriod term,
+			String priceListName,
+			DateTime requestedDate,
+			DateTime subscriptionStartDate) 
+					throws CatalogApiException {
+		return findPlan(new PlanRequestWrapper(productName, term, priceListName), requestedDate, subscriptionStartDate);
+	}
+
+	//
+	// Find a product
+	//
+	@Override
+	public Product findProduct(String name, DateTime requestedDate) throws CatalogApiException {
+		return versionForDate(requestedDate).findCurrentProduct(name);
+	}
+
+
+    //
+    // Find a phase
+    //
+	@Override
+	public PlanPhase findPhase(String phaseName, 
+			DateTime requestedDate,
+			DateTime subscriptionStartDate) 
+					throws CatalogApiException {
+		String planName = DefaultPlanPhase.planName(phaseName);
+		Plan plan = findPlan(planName, requestedDate, subscriptionStartDate);
+		return plan.findPhase(phaseName);
+	}
+	
+    //
+    // Rules
+    //
+	@Override
+	public ActionPolicy planChangePolicy(PlanPhaseSpecifier from,
+			PlanSpecifier to, DateTime requestedDate) throws CatalogApiException {
+		return versionForDate(requestedDate).planChangePolicy(from, to);
+	}
+
+	@Override
+	public ActionPolicy planCancelPolicy(PlanPhaseSpecifier planPhase, DateTime requestedDate) throws CatalogApiException {
+		return versionForDate(requestedDate).planCancelPolicy(planPhase);
+	}
+
+	@Override
+	public PlanAlignmentChange planChangeAlignment(PlanPhaseSpecifier from,
+			PlanSpecifier to, DateTime requestedDate) throws CatalogApiException {
+		return versionForDate(requestedDate).planChangeAlignment(from, to);
 	}
 
 	@Override
-	public Plan findPlan(String productName, BillingPeriod term,
-			String planSetName) throws CatalogApiException {
-		return currentCatalog.findPlan(productName, term, planSetName);
+	public PlanAlignmentCreate planCreateAlignment(PlanSpecifier specifier, DateTime requestedDate) throws CatalogApiException {
+		return versionForDate(requestedDate).planCreateAlignment(specifier);
 	}
 
+	
+
 	@Override
-	public DefaultPlan findPlan(String name) throws CatalogApiException {
-		return currentCatalog.findPlan(name);
+	public BillingAlignment billingAlignment(PlanPhaseSpecifier planPhase, DateTime requestedDate) throws CatalogApiException {
+		return versionForDate(requestedDate).billingAlignment(planPhase);
 	}
 
 	@Override
-	public PlanPhase findPhase(String name) throws CatalogApiException {
-		return currentCatalog.findPhase(name);
+	public PlanChangeResult planChange(PlanPhaseSpecifier from, PlanSpecifier to, DateTime requestedDate)
+			throws CatalogApiException {
+		return versionForDate(requestedDate).planChange(from, to);
 	}
 
 	@Override
-	public Product findProduct(String name) throws CatalogApiException {
-		return currentCatalog.findProduct(name);
+	public boolean canCreatePlan(PlanSpecifier specifier, DateTime requestedDate)
+			throws CatalogApiException {
+		return versionForDate(requestedDate).canCreatePlan(specifier);
 	}
 
+	//
+	// VerifiableConfig API
+	//
 	@Override
 	public void initialize(StandaloneCatalog catalog, URI sourceURI) {
 		for(StandaloneCatalog c : versions) {
@@ -153,48 +337,103 @@ public class VersionedCatalog extends ValidatingConfig<StandaloneCatalog> implem
 		for(StandaloneCatalog c : versions) {
 			errors.addAll(c.validate(c, errors));
 		}
+		//TODO MDW validation - ensure all catalog versions have a single name
+		//TODO MDW validation - ensure effective dates are different (actually do we want this?)
+		//TODO MDW validation - check that all products are there
+		//TODO MDW validation - check that all plans are there
+		//TODO MDW validation - check that all currencies are there
+		//TODO MDW validation - check that all pricelists are there
 		return errors;
 	}
-	
+
+	//
+	// Static catalog API
+	//
+	@Override
+	public Date getEffectiveDate() {
+		return versionForDate(clock.getUTCNow()).getEffectiveDate();
+	}
+
+	@Override
+	public Currency[] getCurrentSupportedCurrencies() {
+		return versionForDate(clock.getUTCNow()).getCurrentSupportedCurrencies();
+	}
+
+	@Override
+	public Product[] getCurrentProducts() {
+		return versionForDate(clock.getUTCNow()).getCurrentProducts() ;
+	}
+
+	@Override
+	public Plan[] getCurrentPlans() {
+		return versionForDate(clock.getUTCNow()).getCurrentPlans();
+	}
+
+	@Override
+	public Plan findCurrentPlan(String productName, BillingPeriod term,
+			String priceList) throws CatalogApiException {
+		return versionForDate(clock.getUTCNow()).findCurrentPlan(productName, term, priceList);
+	}
+
+	@Override
+	public Plan findCurrentPlan(String name) throws CatalogApiException {
+		return versionForDate(clock.getUTCNow()).findCurrentPlan(name);
+	}
+
+	@Override
+	public Product findCurrentProduct(String name) throws CatalogApiException {
+		return versionForDate(clock.getUTCNow()).findCurrentProduct(name);
+	}
+
+	@Override
+	public PlanPhase findCurrentPhase(String name) throws CatalogApiException {
+		return versionForDate(clock.getUTCNow()).findCurrentPhase(name);
+	}
+
 	@Override
 	public ActionPolicy planChangePolicy(PlanPhaseSpecifier from,
 			PlanSpecifier to) throws CatalogApiException {
-		return currentCatalog.planChangePolicy(from, to);
+		return versionForDate(clock.getUTCNow()).planChangePolicy(from, to);
 	}
 
 	@Override
-	public ActionPolicy planCancelPolicy(PlanPhaseSpecifier planPhase) throws CatalogApiException {
-		return currentCatalog.planCancelPolicy(planPhase);
+	public PlanChangeResult planChange(PlanPhaseSpecifier from, PlanSpecifier to)
+			throws CatalogApiException {
+		return versionForDate(clock.getUTCNow()).planChange(from, to);
 	}
 
 	@Override
-	public PlanAlignmentChange planChangeAlignment(PlanPhaseSpecifier from,
-			PlanSpecifier to) throws CatalogApiException {
-		return currentCatalog.planChangeAlignment(from, to);
+	public ActionPolicy planCancelPolicy(PlanPhaseSpecifier planPhase)
+			throws CatalogApiException {
+		return versionForDate(clock.getUTCNow()).planCancelPolicy(planPhase);
 	}
 
 	@Override
-	public PlanAlignmentCreate planCreateAlignment(PlanSpecifier specifier) throws CatalogApiException {
-		return currentCatalog.planCreateAlignment(specifier);
+	public PlanAlignmentCreate planCreateAlignment(PlanSpecifier specifier)
+			throws CatalogApiException {
+		return versionForDate(clock.getUTCNow()).planCreateAlignment(specifier);
 	}
 
 	@Override
-	public String getCatalogName() {
-		return currentCatalog.getCatalogName();
+	public BillingAlignment billingAlignment(PlanPhaseSpecifier planPhase)
+			throws CatalogApiException {
+		return versionForDate(clock.getUTCNow()).billingAlignment(planPhase);
 	}
 
 	@Override
-	public BillingAlignment billingAlignment(PlanPhaseSpecifier planPhase) throws CatalogApiException {
-		return currentCatalog.billingAlignment(planPhase);
+	public PlanAlignmentChange planChangeAlignment(PlanPhaseSpecifier from,
+			PlanSpecifier to) throws CatalogApiException {
+		return versionForDate(clock.getUTCNow()).planChangeAlignment(from, to);
 	}
 
 	@Override
-	public PlanChangeResult planChange(PlanPhaseSpecifier from, PlanSpecifier to)
+	public boolean canCreatePlan(PlanSpecifier specifier)
 			throws CatalogApiException {
-		return currentCatalog.planChange(from, to);
+		return versionForDate(clock.getUTCNow()).canCreatePlan(specifier);
 	}
+
 	
-	//TODO MDW validation - ensure all catalog versions have a single name
-	//TODO MDW validation - ensure effective dates are different (actually do we want this?)
+
+
  
 }
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java b/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
index 089c1e4..765d4bd 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
@@ -57,7 +57,7 @@ public class MockCatalog extends StandaloneCatalog {
 	}
 	
 	public void populatePlans() {
-		DefaultProduct[] products = getProducts();
+		DefaultProduct[] products = getCurrentProducts();
 		DefaultPlan[] plans = new DefaultPlan[products.length];
 		for(int i = 0; i < products.length; i++) {
 			DefaultPlanPhase phase = new DefaultPlanPhase().setPhaseType(PhaseType.EVERGREEN).setBillingPeriod(BillingPeriod.MONTHLY).setReccuringPrice(new DefaultInternationalPrice());
@@ -67,7 +67,7 @@ public class MockCatalog extends StandaloneCatalog {
 	}
 
 	public void populatePriceLists() {
-		DefaultPlan[] plans = getPlans();
+		DefaultPlan[] plans = getCurrentPlans();
 		
 		DefaultPriceList[] priceList = new DefaultPriceList[plans.length - 1];
 		for(int i = 1; i < plans.length; i++) {
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java b/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java
index 5d1af74..773c58b 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java
@@ -24,19 +24,12 @@ import java.util.Date;
 public class MockInternationalPrice extends DefaultInternationalPrice {
 	
 	MockInternationalPrice() {
-		setEffectiveDateForExistingSubscriptons(new Date());
 		setPrices(new DefaultPrice[] {
 			new DefaultPrice().setCurrency(Currency.USD).setValue(new BigDecimal(1))	
 		});
 	}
 	
-	MockInternationalPrice(Date effectiveDateForExistingSubscriptions, DefaultPrice[] price) {
-		setEffectiveDateForExistingSubscriptons(effectiveDateForExistingSubscriptions);
-		setPrices(price);
-	}
-
 	MockInternationalPrice(DefaultPrice... price) {
-		setEffectiveDateForExistingSubscriptons(new Date());
 		setPrices(price);
 	}
 
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java
index 0c2f3b0..10229ef 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java
@@ -16,18 +16,25 @@
 
 package com.ning.billing.catalog.rules;
 
-import com.ning.billing.catalog.DefaultPriceList;
-import com.ning.billing.catalog.DefaultProduct;
-import com.ning.billing.catalog.MockCatalog;
-import com.ning.billing.catalog.StandaloneCatalog;
-import com.ning.billing.catalog.api.*;
-import org.testng.annotations.Test;
+import static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
 
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlIDREF;
 
-import static org.testng.AssertJUnit.assertEquals;
-import static org.testng.AssertJUnit.assertNull;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.ErrorCode;
+import com.ning.billing.catalog.DefaultPriceList;
+import com.ning.billing.catalog.DefaultProduct;
+import com.ning.billing.catalog.MockCatalog;
+import com.ning.billing.catalog.StandaloneCatalog;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.PriceListSet;
+import com.ning.billing.catalog.api.ProductCategory;
 
 public class TestCase {
 
@@ -104,8 +111,8 @@ public class TestCase {
     public void testBasic() throws CatalogApiException{
         MockCatalog cat = new MockCatalog();
 
-        DefaultProduct product = cat.getProducts()[0];
-        DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+        DefaultProduct product = cat.getCurrentProducts()[0];
+        DefaultPriceList priceList = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
 
         CaseResult cr = new CaseResult(
@@ -116,18 +123,18 @@ public class TestCase {
                 Result.FOO);
 
         assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
-        assertionNull(cr, cat.getProducts()[1].getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
+        assertionNull(cr, cat.getCurrentProducts()[1].getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
         assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
         assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
-        assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
+        assertionException(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
     }
 
     @Test(enabled=true)
     public void testWildCardProduct() throws CatalogApiException{
         MockCatalog cat = new MockCatalog();
 
-        DefaultProduct product = cat.getProducts()[0];
-        DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+        DefaultProduct product = cat.getCurrentProducts()[0];
+        DefaultPriceList priceList = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
 
         CaseResult cr = new CaseResult(
@@ -139,18 +146,18 @@ public class TestCase {
                 Result.FOO);
 
         assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
-        assertion(Result.FOO, cr, cat.getProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
+        assertion(Result.FOO, cr, cat.getCurrentProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
         assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
         assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
-        assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
+        assertionException(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
     }
 
     @Test(enabled=true)
     public void testWildCardProductCategory() throws CatalogApiException{
         MockCatalog cat = new MockCatalog();
 
-        DefaultProduct product = cat.getProducts()[0];
-        DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+        DefaultProduct product = cat.getCurrentProducts()[0];
+        DefaultPriceList priceList = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
 
         CaseResult cr = new CaseResult(
@@ -162,18 +169,18 @@ public class TestCase {
                 Result.FOO);
 
         assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
-        assertionNull(cr,  cat.getProducts()[1].getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
+        assertionNull(cr,  cat.getCurrentProducts()[1].getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
         assertion(Result.FOO, cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
         assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
-        assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
+        assertionException(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
     }
 
     @Test(enabled=true)
     public void testWildCardBillingPeriod() throws CatalogApiException{
         MockCatalog cat = new MockCatalog();
 
-        DefaultProduct product = cat.getProducts()[0];
-        DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+        DefaultProduct product = cat.getCurrentProducts()[0];
+        DefaultPriceList priceList = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
 
         CaseResult cr = new CaseResult(
@@ -185,18 +192,18 @@ public class TestCase {
                 Result.FOO);
 
         assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
-        assertionNull(cr,  cat.getProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
+        assertionNull(cr,  cat.getCurrentProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
         assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
         assertion(Result.FOO,cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
-        assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
+        assertionException(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
     }
 
     @Test(enabled=true)
     public void testWildCardPriceList() throws CatalogApiException{
         MockCatalog cat = new MockCatalog();
 
-        DefaultProduct product = cat.getProducts()[0];
-        DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+        DefaultProduct product = cat.getCurrentProducts()[0];
+        DefaultPriceList priceList = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
 
         CaseResult cr = new CaseResult(
@@ -208,7 +215,7 @@ public class TestCase {
                 Result.FOO);
 
         assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
-        assertionNull(cr,  cat.getProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
+        assertionNull(cr,  cat.getCurrentProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
         assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
         assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
         assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
@@ -218,8 +225,8 @@ public class TestCase {
     public void testCaseOrder() throws CatalogApiException {
         MockCatalog cat = new MockCatalog();
 
-        DefaultProduct product = cat.getProducts()[0];
-        DefaultPriceList priceList = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+        DefaultProduct product = cat.getCurrentProducts()[0];
+        DefaultPriceList priceList = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
 
         CaseResult cr0 = new CaseResult(
@@ -266,6 +273,15 @@ public class TestCase {
         assertNull(cr.getResult(new PlanSpecifier(productName, productCategory, bp, priceListName), cat));
     }
 
+    protected void assertionException(CaseResult cr, String productName, ProductCategory productCategory, BillingPeriod bp, String priceListName, StandaloneCatalog cat) {
+        try{
+        	cr.getResult(new PlanSpecifier(productName, productCategory, bp, priceListName), cat);  	
+        	Assert.fail("Expecting an exception");
+        } catch (CatalogApiException e) {
+        	Assert.assertEquals(e.getCode(), ErrorCode.CAT_PRICE_LIST_NOT_FOUND.getCode());
+        }
+    }
+
     protected void assertion(Result result, CaseResult cr, String productName, ProductCategory productCategory, BillingPeriod bp, String priceListName,StandaloneCatalog cat) throws CatalogApiException{
         assertEquals(result, cr.getResult(new PlanSpecifier(productName, productCategory, bp, priceListName), cat));
     }
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java
index af13162..f684503 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java
@@ -16,11 +16,14 @@
 
 package com.ning.billing.catalog.rules;
 
+import com.ning.billing.ErrorCode;
 import com.ning.billing.catalog.DefaultPriceList;
 import com.ning.billing.catalog.DefaultProduct;
 import com.ning.billing.catalog.MockCatalog;
 import com.ning.billing.catalog.StandaloneCatalog;
 import com.ning.billing.catalog.api.*;
+import com.ning.billing.catalog.rules.TestCase.CaseResult;
+
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -60,13 +63,13 @@ public class TestCaseChange {
 		}
 	}
 	@Test(enabled=true)
-	public void testBasic(){
+	public void testBasic() throws CatalogApiException{
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product1 = cat.getProducts()[0];
-		DefaultPriceList priceList1 = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+		DefaultProduct product1 = cat.getCurrentProducts()[0];
+		DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
-		DefaultProduct product2 = cat.getProducts()[2];
+		DefaultProduct product2 = cat.getCurrentProducts()[2];
 		DefaultPriceList priceList2 = cat.getPriceLists().getChildPriceLists()[1];
 
 
@@ -86,14 +89,14 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				 cat.getProducts()[1].getName(), product2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				product1.getName(),  cat.getProducts()[1].getName(), 
+				product1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -127,18 +130,18 @@ public class TestCaseChange {
 				priceList1.getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				 cat.getProducts()[1].getName(), priceList2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				priceList1.getName(),  cat.getProducts()[1].getName(), 
+				priceList1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
@@ -150,13 +153,13 @@ public class TestCaseChange {
 	}
 	
 	@Test(enabled=true)
-	public void testWildcardFromProduct(){
+	public void testWildcardFromProduct()throws CatalogApiException{
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product1 = cat.getProducts()[0];
-		DefaultPriceList priceList1 = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+		DefaultProduct product1 = cat.getCurrentProducts()[0];
+		DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
-		DefaultProduct product2 = cat.getProducts()[2];
+		DefaultProduct product2 = cat.getCurrentProducts()[2];
 		DefaultPriceList priceList2 = cat.getPriceLists().getChildPriceLists()[1];
 
 
@@ -176,7 +179,7 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertion(Result.FOO,cr, 
-				 cat.getProducts()[1].getName(), product2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -197,7 +200,7 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 
 		assertionNull(cr, 
-				product1.getName(),  cat.getProducts()[1].getName(), 
+				product1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.ANNUAL, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -210,18 +213,18 @@ public class TestCaseChange {
 				priceList1.getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				 cat.getProducts()[1].getName(), priceList2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				priceList1.getName(),  cat.getProducts()[1].getName(), 
+				priceList1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
@@ -233,13 +236,13 @@ public class TestCaseChange {
 	}
 	
 	@Test(enabled=true)
-	public void testWildcardToProduct(){
+	public void testWildcardToProduct() throws CatalogApiException{
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product1 = cat.getProducts()[0];
-		DefaultPriceList priceList1 = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+		DefaultProduct product1 = cat.getCurrentProducts()[0];
+		DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
-		DefaultProduct product2 = cat.getProducts()[2];
+		DefaultProduct product2 = cat.getCurrentProducts()[2];
 		DefaultPriceList priceList2 = cat.getPriceLists().getChildPriceLists()[1];
 
 
@@ -259,7 +262,7 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				 cat.getProducts()[1].getName(), product2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -280,7 +283,7 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertion(Result.FOO, cr, 
-				product1.getName(),  cat.getProducts()[1].getName(), 
+				product1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -300,18 +303,18 @@ public class TestCaseChange {
 				priceList1.getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				 cat.getProducts()[1].getName(), priceList2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				priceList1.getName(),  cat.getProducts()[1].getName(), 
+				priceList1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
@@ -323,13 +326,13 @@ public class TestCaseChange {
 	}
 	
 	@Test(enabled=true)
-	public void testWildcardFromProductCategory(){
+	public void testWildcardFromProductCategory() throws CatalogApiException{
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product1 = cat.getProducts()[0];
-		DefaultPriceList priceList1 = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+		DefaultProduct product1 = cat.getCurrentProducts()[0];
+		DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
-		DefaultProduct product2 = cat.getProducts()[2];
+		DefaultProduct product2 = cat.getCurrentProducts()[2];
 		DefaultPriceList priceList2 = cat.getPriceLists().getChildPriceLists()[1];
 
 
@@ -349,14 +352,14 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				 cat.getProducts()[1].getName(), product2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				product1.getName(),  cat.getProducts()[1].getName(), 
+				product1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -390,18 +393,18 @@ public class TestCaseChange {
 				priceList1.getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				 cat.getProducts()[1].getName(), priceList2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				priceList1.getName(),  cat.getProducts()[1].getName(), 
+				priceList1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
@@ -413,13 +416,13 @@ public class TestCaseChange {
 	}
 	
 	@Test(enabled=true)
-	public void testWildcardToProductCategory(){
+	public void testWildcardToProductCategory() throws CatalogApiException{
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product1 = cat.getProducts()[0];
-		DefaultPriceList priceList1 = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+		DefaultProduct product1 = cat.getCurrentProducts()[0];
+		DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
-		DefaultProduct product2 = cat.getProducts()[2];
+		DefaultProduct product2 = cat.getCurrentProducts()[2];
 		DefaultPriceList priceList2 = cat.getPriceLists().getChildPriceLists()[1];
 
 
@@ -439,14 +442,14 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				 cat.getProducts()[1].getName(), product2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				product1.getName(),  cat.getProducts()[1].getName(), 
+				product1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -480,18 +483,18 @@ public class TestCaseChange {
 				priceList1.getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				 cat.getProducts()[1].getName(), priceList2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				priceList1.getName(),  cat.getProducts()[1].getName(), 
+				priceList1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
@@ -503,13 +506,13 @@ public class TestCaseChange {
 	}
 	
 	@Test(enabled=true)
-	public void testWildcardFromBillingPeriod(){
+	public void testWildcardFromBillingPeriod() throws CatalogApiException{
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product1 = cat.getProducts()[0];
-		DefaultPriceList priceList1 = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+		DefaultProduct product1 = cat.getCurrentProducts()[0];
+		DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
-		DefaultProduct product2 = cat.getProducts()[2];
+		DefaultProduct product2 = cat.getCurrentProducts()[2];
 		DefaultPriceList priceList2 = cat.getPriceLists().getChildPriceLists()[1];
 
 
@@ -529,7 +532,7 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				 cat.getProducts()[1].getName(), product2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -550,7 +553,7 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				product1.getName(),  cat.getProducts()[1].getName(), 
+				product1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -570,18 +573,18 @@ public class TestCaseChange {
 				priceList1.getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				 cat.getProducts()[1].getName(), priceList2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				priceList1.getName(),  cat.getProducts()[1].getName(), 
+				priceList1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
@@ -594,13 +597,13 @@ public class TestCaseChange {
 	
 	
 	@Test(enabled=true)
-	public void testWildCardToBillingPeriod(){
+	public void testWildCardToBillingPeriod() throws CatalogApiException{
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product1 = cat.getProducts()[0];
-		DefaultPriceList priceList1 = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+		DefaultProduct product1 = cat.getCurrentProducts()[0];
+		DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
-		DefaultProduct product2 = cat.getProducts()[2];
+		DefaultProduct product2 = cat.getCurrentProducts()[2];
 		DefaultPriceList priceList2 = cat.getPriceLists().getChildPriceLists()[1];
 
 
@@ -620,7 +623,7 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				 cat.getProducts()[1].getName(), product2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -641,7 +644,7 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				product1.getName(),  cat.getProducts()[1].getName(), 
+				product1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -661,18 +664,18 @@ public class TestCaseChange {
 				priceList1.getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				 cat.getProducts()[1].getName(), priceList2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				priceList1.getName(),  cat.getProducts()[1].getName(), 
+				priceList1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
@@ -684,13 +687,13 @@ public class TestCaseChange {
 	}
 	
 	@Test(enabled=true)
-	public void testWildCardFromPriceList(){
+	public void testWildCardFromPriceList() throws CatalogApiException{
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product1 = cat.getProducts()[0];
-		DefaultPriceList priceList1 = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+		DefaultProduct product1 = cat.getCurrentProducts()[0];
+		DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
-		DefaultProduct product2 = cat.getProducts()[2];
+		DefaultProduct product2 = cat.getCurrentProducts()[2];
 		DefaultPriceList priceList2 = cat.getPriceLists().getChildPriceLists()[1];
 
 
@@ -710,7 +713,7 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				 cat.getProducts()[1].getName(), product2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -731,7 +734,7 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				product1.getName(),  cat.getProducts()[1].getName(), 
+				product1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -755,14 +758,14 @@ public class TestCaseChange {
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				 cat.getProducts()[1].getName(), priceList2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				priceList1.getName(),  cat.getProducts()[1].getName(), 
+				priceList1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
@@ -774,13 +777,13 @@ public class TestCaseChange {
 	}
 	
 	@Test(enabled=true)
-	public void testWildcardToPriceList(){
+	public void testWildcardToPriceList() throws CatalogApiException{
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product1 = cat.getProducts()[0];
-		DefaultPriceList priceList1 = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+		DefaultProduct product1 = cat.getCurrentProducts()[0];
+		DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
-		DefaultProduct product2 = cat.getProducts()[2];
+		DefaultProduct product2 = cat.getCurrentProducts()[2];
 		DefaultPriceList priceList2 = cat.getPriceLists().getChildPriceLists()[1];
 
 
@@ -800,7 +803,7 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				 cat.getProducts()[1].getName(), product2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -821,7 +824,7 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				product1.getName(),  cat.getProducts()[1].getName(), 
+				product1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -841,18 +844,18 @@ public class TestCaseChange {
 				priceList1.getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				 cat.getProducts()[1].getName(), priceList2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
 		assertion(Result.FOO,cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				priceList1.getName(),  cat.getProducts()[1].getName(), 
+				priceList1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
@@ -864,13 +867,13 @@ public class TestCaseChange {
 	}
 	
 	@Test(enabled=true)
-	public void testWildcardPlanPhase(){
+	public void testWildcardPlanPhase() throws CatalogApiException{
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product1 = cat.getProducts()[0];
-		DefaultPriceList priceList1 = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+		DefaultProduct product1 = cat.getCurrentProducts()[0];
+		DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
-		DefaultProduct product2 = cat.getProducts()[2];
+		DefaultProduct product2 = cat.getCurrentProducts()[2];
 		DefaultPriceList priceList2 = cat.getPriceLists().getChildPriceLists()[1];
 
 
@@ -890,7 +893,7 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				 cat.getProducts()[1].getName(), product2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -911,7 +914,7 @@ public class TestCaseChange {
 				PhaseType.EVERGREEN, cat);
 		
 		assertionNull(cr, 
-				product1.getName(),  cat.getProducts()[1].getName(), 
+				product1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
 				priceList1.getName(), priceList2.getName(), 
@@ -931,18 +934,18 @@ public class TestCaseChange {
 				priceList1.getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				 cat.getProducts()[1].getName(), priceList2.getName(), 
+				 cat.getCurrentProducts()[1].getName(), priceList2.getName(), 
 				PhaseType.EVERGREEN, cat);
 		
-		assertionNull(cr, 
+		assertionException(cr, 
 				product1.getName(), product2.getName(), 
 				ProductCategory.BASE, ProductCategory.BASE,
 				BillingPeriod.MONTHLY, BillingPeriod.MONTHLY, 
-				priceList1.getName(),  cat.getProducts()[1].getName(), 
+				priceList1.getName(),  cat.getCurrentProducts()[1].getName(), 
 				PhaseType.EVERGREEN, cat);
 		
 		assertion(Result.FOO,cr, 
@@ -958,10 +961,10 @@ public class TestCaseChange {
 	public void testOrder() throws CatalogApiException{
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product1 = cat.getProducts()[0];
-		DefaultPriceList priceList1 = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+		DefaultProduct product1 = cat.getCurrentProducts()[0];
+		DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 
-		DefaultProduct product2 = cat.getProducts()[2];
+		DefaultProduct product2 = cat.getCurrentProducts()[2];
 		DefaultPriceList priceList2 = cat.getPriceLists().getChildPriceLists()[1];
 
 
@@ -1033,7 +1036,20 @@ public class TestCaseChange {
 			Assert.fail("", e);
 		}
 	}
-
+	   protected void assertionException(CaseChangeResult cr, 
+				String fromProductName, String toProductName,
+				ProductCategory fromProductCategory, ProductCategory toProductCategory, 
+				BillingPeriod fromBp, BillingPeriod toBp,
+				String fromPriceListName, String toPriceListName,
+				PhaseType phaseType, StandaloneCatalog cat){
+	        try{
+	        	cr.getResult(new PlanPhaseSpecifier(fromProductName, fromProductCategory, fromBp, fromPriceListName, phaseType), 
+						new PlanSpecifier(toProductName, toProductCategory, toBp, toPriceListName),cat);	
+	        	Assert.fail("Expecting an exception");
+	        } catch (CatalogApiException e) {
+	        	Assert.assertEquals(e.getCode(), ErrorCode.CAT_PRICE_LIST_NOT_FOUND.getCode());
+	        }
+	    }
 	protected void assertion(Result result, CaseChangeResult cr, 
 			String fromProductName, String toProductName,
 			ProductCategory fromProductCategory, ProductCategory toProductCategory, 
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java
index fe505f4..02f7ab5 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.catalog.rules;
 
+import com.ning.billing.ErrorCode;
 import com.ning.billing.catalog.DefaultPriceList;
 import com.ning.billing.catalog.DefaultProduct;
 import com.ning.billing.catalog.MockCatalog;
@@ -53,7 +54,7 @@ public class TestCasePhase {
 	public void testBasic(){
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product = cat.getProducts()[0];
+		DefaultProduct product = cat.getCurrentProducts()[0];
 		DefaultPriceList priceList = cat.getPriceLists().getDefaultPricelist();
 
 
@@ -66,10 +67,10 @@ public class TestCasePhase {
 				Result.FOO);
 
 		assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
-		assertionNull(cr,  cat.getProducts()[1].getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+		assertionNull(cr,  cat.getCurrentProducts()[1].getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
 		assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
 		assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), PhaseType.EVERGREEN, cat);
-		assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
+		assertionException(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
 		assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.TRIAL, cat);
 	}
 
@@ -77,7 +78,7 @@ public class TestCasePhase {
 	public void testWildCardProduct(){
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product = cat.getProducts()[0];
+		DefaultProduct product = cat.getCurrentProducts()[0];
 		DefaultPriceList priceList = cat.getPriceLists().getDefaultPricelist();
 
 
@@ -90,10 +91,10 @@ public class TestCasePhase {
 				Result.FOO);
 
 		assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
-		assertion(Result.FOO, cr, cat.getProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+		assertion(Result.FOO, cr, cat.getCurrentProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
 		assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
 		assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), PhaseType.EVERGREEN, cat);
-		assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
+		assertionException(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
 		assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.TRIAL, cat);
 	}
 	
@@ -101,7 +102,7 @@ public class TestCasePhase {
 	public void testWildCardProductCategory(){
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product = cat.getProducts()[0];
+		DefaultProduct product = cat.getCurrentProducts()[0];
 		DefaultPriceList priceList = cat.getPriceLists().getDefaultPricelist();
 
 
@@ -114,10 +115,10 @@ public class TestCasePhase {
 				Result.FOO);
 
 		assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
-		assertionNull(cr,  cat.getProducts()[1].getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+		assertionNull(cr,  cat.getCurrentProducts()[1].getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
 		assertion(Result.FOO, cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
 		assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), PhaseType.EVERGREEN, cat);
-		assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
+		assertionException(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
 		assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.TRIAL, cat);
 	}
 	
@@ -125,7 +126,7 @@ public class TestCasePhase {
 	public void testWildCardBillingPeriod(){
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product = cat.getProducts()[0];
+		DefaultProduct product = cat.getCurrentProducts()[0];
 		DefaultPriceList priceList = cat.getPriceLists().getDefaultPricelist();
 
 
@@ -138,10 +139,10 @@ public class TestCasePhase {
 				Result.FOO);
 
 		assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
-		assertionNull(cr,  cat.getProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+		assertionNull(cr,  cat.getCurrentProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
 		assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
 		assertion(Result.FOO,cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), PhaseType.EVERGREEN, cat);
-		assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
+		assertionException(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
 		assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.TRIAL, cat);
 	}
 
@@ -149,7 +150,7 @@ public class TestCasePhase {
 	public void testWildCardPriceList(){
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product = cat.getProducts()[0];
+		DefaultProduct product = cat.getCurrentProducts()[0];
 		DefaultPriceList priceList = cat.getPriceLists().getDefaultPricelist();
 
 
@@ -162,7 +163,7 @@ public class TestCasePhase {
 				Result.FOO);
 
 		assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
-		assertionNull(cr,  cat.getProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+		assertionNull(cr,  cat.getCurrentProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
 		assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
 		assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), PhaseType.EVERGREEN, cat);
 		assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
@@ -173,7 +174,7 @@ public class TestCasePhase {
 	public void testWildCardPhaseType(){
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product = cat.getProducts()[0];
+		DefaultProduct product = cat.getCurrentProducts()[0];
 		DefaultPriceList priceList = cat.getPriceLists().getDefaultPricelist();
 
 
@@ -186,10 +187,10 @@ public class TestCasePhase {
 				Result.FOO);
 
 		assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
-		assertionNull(cr,  cat.getProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+		assertionNull(cr,  cat.getCurrentProducts()[1].getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
 		assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
 		assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), PhaseType.EVERGREEN, cat);
-		assertionNull(cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
+		assertionException(cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
 		assertion(Result.FOO,cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.TRIAL, cat);
 	}
 	
@@ -197,7 +198,7 @@ public class TestCasePhase {
 	public void testOrder() throws CatalogApiException{
 		MockCatalog cat = new MockCatalog();
 
-		DefaultProduct product = cat.getProducts()[0];
+		DefaultProduct product = cat.getCurrentProducts()[0];
 		DefaultPriceList priceList = cat.getPriceLists().getDefaultPricelist();
 
 
@@ -262,6 +263,16 @@ public class TestCasePhase {
 		}
 	}
 
+
+	protected void assertionException(CaseResult cr, String productName, ProductCategory productCategory, BillingPeriod bp, String priceListName, PhaseType phaseType, StandaloneCatalog cat){
+		try {
+			Assert.assertNull(cr.getResult(new PlanPhaseSpecifier(productName, productCategory, bp, priceListName, phaseType), cat));
+			Assert.fail("Exception expected");
+		} catch (CatalogApiException e) {
+			Assert.assertEquals(e.getCode(), ErrorCode.CAT_PRICE_LIST_NOT_FOUND.getCode());
+		}
+	}
+
 	protected void assertion(Result result, CaseResult cr, String productName, ProductCategory productCategory, BillingPeriod bp, String priceListName, PhaseType phaseType, StandaloneCatalog cat){
 		try {
 			Assert.assertEquals(result, cr.getResult(new PlanPhaseSpecifier(productName, productCategory, bp, priceListName, phaseType), cat));
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestPlanRules.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestPlanRules.java
index e41d506..7ac9cc0 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestPlanRules.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestPlanRules.java
@@ -20,6 +20,7 @@ import com.ning.billing.catalog.DefaultPriceList;
 import com.ning.billing.catalog.DefaultProduct;
 import com.ning.billing.catalog.MockCatalog;
 import com.ning.billing.catalog.api.*;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.testng.Assert;
@@ -48,9 +49,9 @@ public class TestPlanRules {
 	}
 
 	@Test
-	public void testCannotChangeToSamePlan() {
-		DefaultProduct product1 = cat.getProducts()[0];
-		DefaultPriceList priceList1 = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+	public void testCannotChangeToSamePlan() throws CatalogApiException {
+		DefaultProduct product1 = cat.getCurrentProducts()[0];
+		DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 		
 		PlanPhaseSpecifier from = new PlanPhaseSpecifier(product1.getName(), product1.getCategory(), BillingPeriod.MONTHLY, priceList1.getName(), PhaseType.EVERGREEN);
 		PlanSpecifier to = new PlanSpecifier(product1.getName(), product1.getCategory(), BillingPeriod.MONTHLY, priceList1.getName());
@@ -67,9 +68,9 @@ public class TestPlanRules {
 	}
 	
 	@Test
-	public void testExistingPriceListIsKept() {
-		DefaultProduct product1 = cat.getProducts()[0];
-		DefaultPriceList priceList1 = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+	public void testExistingPriceListIsKept() throws CatalogApiException {
+		DefaultProduct product1 = cat.getCurrentProducts()[0];
+		DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 		
 		PlanPhaseSpecifier from = new PlanPhaseSpecifier(product1.getName(), product1.getCategory(), BillingPeriod.MONTHLY, priceList1.getName(), PhaseType.EVERGREEN);
 		PlanSpecifier to = new PlanSpecifier(product1.getName(), product1.getCategory(), BillingPeriod.ANNUAL, priceList1.getName());
@@ -92,10 +93,10 @@ public class TestPlanRules {
 	
 	
 	@Test
-	public void testBaseCase() {
-		DefaultProduct product1 = cat.getProducts()[0];
-		DefaultProduct product2 = cat.getProducts()[1];
-		DefaultPriceList priceList1 = cat.getPriceListFromName(PriceListSet.DEFAULT_PRICELIST_NAME);
+	public void testBaseCase() throws CatalogApiException {
+		DefaultProduct product1 = cat.getCurrentProducts()[0];
+		DefaultProduct product2 = cat.getCurrentProducts()[1];
+		DefaultPriceList priceList1 = cat.findCurrentPriceList(PriceListSet.DEFAULT_PRICELIST_NAME);
 		DefaultPriceList priceList2 = cat.getPriceLists().getChildPriceLists()[0];
 		
 		PlanPhaseSpecifier from = new PlanPhaseSpecifier(product1.getName(), product1.getCategory(), BillingPeriod.MONTHLY, priceList1.getName(), PhaseType.EVERGREEN);
@@ -103,7 +104,7 @@ public class TestPlanRules {
 
 		PlanChangeResult result = null;
 		try {
-			result = cat.getPlanRules().planChange(from, to, cat);		
+			result = cat.getPlanRules().planChange(from, to, cat);	
 		} catch (IllegalPlanChange e) {
 			log.info("Correct - cannot change to the same plan:", e);
 			Assert.fail("We should not have triggered this error");
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestCatalogService.java b/catalog/src/test/java/com/ning/billing/catalog/TestCatalogService.java
index 754b03a..7bb45a6 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestCatalogService.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestCatalogService.java
@@ -35,8 +35,8 @@ public class TestCatalogService {
 			
 		}, new VersionedCatalogLoader(new DefaultClock()));
 		service.loadCatalog();
-		Assert.assertNotNull(service.getCatalog());
-		Assert.assertEquals(service.getCatalog().getCatalogName(), "WeaponsHireSmall");
+		Assert.assertNotNull(service.getFullCatalog());
+		Assert.assertEquals(service.getFullCatalog().getCatalogName(), "WeaponsHireSmall");
 	}
 	
 	@Test
@@ -49,7 +49,7 @@ public class TestCatalogService {
 			
 		}, new VersionedCatalogLoader(new DefaultClock()));
 		service.loadCatalog();
-		Assert.assertNotNull(service.getCatalog());
-		Assert.assertEquals(service.getCatalog().getCatalogName(), "Firearms");
+		Assert.assertNotNull(service.getFullCatalog());
+		Assert.assertEquals(service.getFullCatalog().getCatalogName(), "Firearms");
 	}
 }
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java b/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java
index 0f75459..3e6a755 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java
@@ -67,7 +67,7 @@ public class TestInternationalPrice {
 	  StandaloneCatalog c = new MockCatalog();
 	  c.setSupportedCurrencies(new Currency[]{Currency.GBP, Currency.EUR, Currency.USD, Currency.BRL, Currency.MXN});
 	  c.initialize(c, new URI("foo://bar"));
-	  Assert.assertEquals(c.getPlans()[0].getFinalPhase().getRecurringPrice().getPrice(Currency.GBP), new BigDecimal(0));
+	  Assert.assertEquals(c.getCurrentPlans()[0].getFinalPhase().getRecurringPrice().getPrice(Currency.GBP), new BigDecimal(0));
   }
   
   @Test
@@ -88,16 +88,7 @@ public class TestInternationalPrice {
 	 errors.log(log);
 	 Assert.assertEquals(errors.size(), 3);
   }
-  @Test
-  public void testDateValidation(){
-	 StandaloneCatalog c = new MockCatalog();
-	 c.setSupportedCurrencies(new Currency[]{Currency.GBP, Currency.EUR, Currency.USD, Currency.BRL, Currency.MXN});
-	 DefaultInternationalPrice p1 =  new MockInternationalPrice();
-	 p1.setEffectiveDateForExistingSubscriptons(new Date((new Date().getTime()) - (1000 * 60 * 60 * 24)));
-	 ValidationErrors errors = p1.validate(c, new ValidationErrors());
-	 Assert.assertEquals(errors.size(), 1);
-	 errors.log(log);
-  }
+
   
   
   
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestPlan.java b/catalog/src/test/java/com/ning/billing/catalog/TestPlan.java
new file mode 100644
index 0000000..00dd1b6
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestPlan.java
@@ -0,0 +1,43 @@
+/*
+ * 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.catalog;
+
+import java.util.Date;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.config.ValidationErrors;
+
+public class TestPlan {
+	private static final Logger log = LoggerFactory.getLogger(TestPlan.class);
+	@Test
+	public void testDateValidation() {
+
+		StandaloneCatalog c = new MockCatalog();
+		c.setSupportedCurrencies(new Currency[]{Currency.GBP, Currency.EUR, Currency.USD, Currency.BRL, Currency.MXN});
+		DefaultPlan p1 =  new MockPlan();
+		p1.setEffectiveDateForExistingSubscriptons(new Date((new Date().getTime()) - (1000 * 60 * 60 * 24)));
+		ValidationErrors errors = p1.validate(c, new ValidationErrors());
+		Assert.assertEquals(errors.size(), 1);
+		errors.log(log);
+
+	}
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java b/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java
index 4bfcf30..d778c4b 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java
@@ -17,6 +17,8 @@
 package com.ning.billing.catalog;
 
 import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.PhaseType;
 import com.ning.billing.util.config.ValidationErrors;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -44,5 +46,37 @@ public class TestPlanPhase {
 		errors = pp.validate(new MockCatalog(), new ValidationErrors());
 		errors.log(log);
 		Assert.assertEquals(errors.size(), 1);
-}
+	}
+	
+	@Test
+	public void testPhaseNames() throws CatalogApiException {
+		String planName = "Foo";
+		String planNameExt = planName + "-";
+		
+		DefaultPlan p = new MockPlan().setName(planName);
+		DefaultPlanPhase ppDiscount = new MockPlanPhase().setPhaseType(PhaseType.DISCOUNT).setPlan(p);
+		DefaultPlanPhase ppTrial = new MockPlanPhase().setPhaseType(PhaseType.TRIAL).setPlan(p);
+		DefaultPlanPhase ppEvergreen = new MockPlanPhase().setPhaseType(PhaseType.EVERGREEN).setPlan(p);
+		DefaultPlanPhase ppFixedterm = new MockPlanPhase().setPhaseType(PhaseType.FIXEDTERM).setPlan(p);
+		
+		String ppnDiscount = DefaultPlanPhase.phaseName(p, ppDiscount);
+		String ppnTrial = DefaultPlanPhase.phaseName(p, ppTrial);
+		String ppnEvergreen = DefaultPlanPhase.phaseName(p, ppEvergreen);
+		String ppnFixedterm = DefaultPlanPhase.phaseName(p, ppFixedterm);
+		
+		Assert.assertEquals(ppnTrial, planNameExt + "trial");
+		Assert.assertEquals(ppnEvergreen, planNameExt + "evergreen");
+		Assert.assertEquals(ppnFixedterm, planNameExt + "fixedterm");
+		Assert.assertEquals(ppnDiscount, planNameExt + "discount");
+		
+		
+		Assert.assertEquals(DefaultPlanPhase.planName(ppnDiscount),planName);
+		Assert.assertEquals(DefaultPlanPhase.planName(ppnTrial),planName);
+		Assert.assertEquals(DefaultPlanPhase.planName(ppnEvergreen), planName);
+		Assert.assertEquals(DefaultPlanPhase.planName(ppnFixedterm), planName);
+		
+		
+		
+		
+	}
 }
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java b/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
index 09024ce..3cb8d2f 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
@@ -17,6 +17,7 @@
 package com.ning.billing.catalog;
 
 import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.CatalogApiException;
 import com.ning.billing.catalog.api.PhaseType;
 import com.ning.billing.catalog.api.PriceListSet;
 import com.ning.billing.catalog.api.ProductCategory;
@@ -30,7 +31,7 @@ import static com.ning.billing.catalog.api.PhaseType.EVERGREEN;
 
 public class TestPriceListSet {
 	@Test(enabled=true)
-	public void testOverriding() {
+	public void testOverriding() throws CatalogApiException {
 		DefaultProduct foo = new DefaultProduct("Foo", ProductCategory.BASE);
 		DefaultProduct bar = new DefaultProduct("Bar", ProductCategory.BASE);
 		DefaultPlan[] defaultPlans = new DefaultPlan[]{ 
@@ -55,7 +56,7 @@ public class TestPriceListSet {
 		Assert.assertEquals(set.getPlanListFrom("child", foo, BillingPeriod.MONTHLY).getFinalPhase().getPhaseType(), PhaseType.EVERGREEN);
 	}
 	
-	public void testForNullBillingPeriod() {
+	public void testForNullBillingPeriod() throws CatalogApiException {
 		DefaultProduct foo = new DefaultProduct("Foo", ProductCategory.BASE);
 		DefaultProduct bar = new DefaultProduct("Bar", ProductCategory.BASE);
 		DefaultPlan[] defaultPlans = new DefaultPlan[]{ 
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestStandaloneCatalog.java b/catalog/src/test/java/com/ning/billing/catalog/TestStandaloneCatalog.java
new file mode 100644
index 0000000..fd5d8fb
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestStandaloneCatalog.java
@@ -0,0 +1,52 @@
+/*
+ * 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.catalog;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.PhaseType;
+
+public class TestStandaloneCatalog {
+	
+		@Test
+		public void testFindPhase() throws CatalogApiException{
+			DefaultPlanPhase phaseTrial1 = new MockPlanPhase().setPhaseType(PhaseType.TRIAL);
+			DefaultPlanPhase phaseTrial2 = new MockPlanPhase().setPhaseType(PhaseType.TRIAL);
+			DefaultPlanPhase phaseDiscount1 = new MockPlanPhase().setPhaseType(PhaseType.DISCOUNT);
+			DefaultPlanPhase phaseDiscount2 = new MockPlanPhase().setPhaseType(PhaseType.DISCOUNT);
+			
+			DefaultPlan plan1 = new MockPlan().setName("TestPlan1").setFinalPhase(phaseDiscount1).setInitialPhases(new DefaultPlanPhase[]{phaseTrial1});
+			DefaultPlan plan2 = new MockPlan().setName("TestPlan2").setFinalPhase(phaseDiscount2).setInitialPhases(new DefaultPlanPhase[]{phaseTrial2});
+			phaseTrial1.setPlan(plan1);
+			phaseTrial2.setPlan(plan2);
+			phaseDiscount1.setPlan(plan1);
+			phaseDiscount2.setPlan(plan2);
+			
+			StandaloneCatalog cat = new MockCatalog().setPlans(new DefaultPlan[]{plan1, plan2});
+			
+			Assert.assertEquals(cat.findCurrentPhase("TestPlan1-discount"), phaseDiscount1);
+			Assert.assertEquals(cat.findCurrentPhase("TestPlan2-discount"), phaseDiscount2);
+			Assert.assertEquals(cat.findCurrentPhase("TestPlan1-trial"), phaseTrial1);
+			Assert.assertEquals(cat.findCurrentPhase("TestPlan2-trial"), phaseTrial2);
+			
+			
+		}
+		
+		
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java b/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
index bc07e3e..ddd623e 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
@@ -15,56 +15,88 @@
  */
 package com.ning.billing.catalog;
 
-import com.google.common.io.Resources;
-import com.ning.billing.catalog.api.InvalidConfigException;
-import com.ning.billing.catalog.io.VersionedCatalogLoader;
-import com.ning.billing.lifecycle.KillbillService.ServiceException;
-import com.ning.billing.util.clock.DefaultClock;
-import org.joda.time.DateTime;
-import org.testng.annotations.Test;
-import org.xml.sax.SAXException;
+import static org.testng.AssertJUnit.assertEquals;
 
-import javax.xml.bind.JAXBException;
-import javax.xml.transform.TransformerException;
 import java.io.IOException;
+import java.math.BigDecimal;
 import java.net.MalformedURLException;
 import java.net.URISyntaxException;
 import java.util.Date;
 
-import static org.testng.AssertJUnit.assertEquals;
+import javax.xml.bind.JAXBException;
+import javax.xml.transform.TransformerException;
+
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+import org.xml.sax.SAXException;
+
+import com.google.common.io.Resources;
+import com.ning.billing.catalog.api.CatalogApiException;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.InvalidConfigException;
+import com.ning.billing.catalog.api.Plan;
+import com.ning.billing.catalog.io.VersionedCatalogLoader;
+import com.ning.billing.lifecycle.KillbillService.ServiceException;
+import com.ning.billing.util.clock.DefaultClock;
 
 public class TestVersionedCatalog {
+	private static final Logger log = LoggerFactory.getLogger(TestVersionedCatalog.class);
 	private final VersionedCatalogLoader loader = new VersionedCatalogLoader(new DefaultClock());
+	private VersionedCatalog vc;
+	
+	@BeforeClass(groups={"setup"})
+	public void setUp() throws ServiceException {
+		vc = loader.load(Resources.getResource("versionedCatalog").toString());
+	}
 
 	@Test(enabled=true)
-	public void testAddCatalog() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException, ServiceException {
-		VersionedCatalog vc = loader.load(Resources.getResource("versionedCatalog").toString());
+	public void testAddCatalog() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException, ServiceException, CatalogApiException {
 		vc.add(new StandaloneCatalog(new Date()));
 		assertEquals(5, vc.size());
 	}
 	
+		
 	@Test(enabled=true)
-	public void testApplyEffectiveDate() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException, ServiceException {
-		VersionedCatalog vc = loader.load(Resources.getResource("versionedCatalog").toString());
-		Date d = new Date(1L);
-		vc.configureEffectiveDate(d);
-		assertEquals(new Date(0), vc.getEffectiveDate()); // Start at the begining of time
+	public void testFindPlanWithDates() throws Exception {
+		DateTime dt0= new DateTime("2010-01-01T00:00:00+00:00");
+		DateTime dt1 = new DateTime("2011-01-01T00:01:00+00:00");
+		DateTime dt2 = new DateTime("2011-02-02T00:01:00+00:00");
+		DateTime dt214 = new DateTime("2011-02-14T00:01:00+00:00");
+		DateTime dt3 = new DateTime("2011-03-03T00:01:00+00:00");
 		
-		DateTime dt = new DateTime("2011-01-01T00:00:00+00:00");
-		d = new Date(dt.getMillis() + 1000);
-		vc.configureEffectiveDate(d);
-		assertEquals(dt.toDate(),vc.getEffectiveDate());
+		// New subscription
+		try {
+			vc.findPlan("pistol-monthly", dt0, dt0);	
+			Assert.fail("Exception should have been thrown there are no plans for this date");
+		} catch (CatalogApiException e) {
+			// Expected behaviour
+			log.error("Expected exception", e);
+			
+		}
+		Plan newSubPlan1 = vc.findPlan("pistol-monthly", dt1, dt1);
+		Plan newSubPlan2 = vc.findPlan("pistol-monthly", dt2, dt2);
+		Plan newSubPlan214 = vc.findPlan("pistol-monthly", dt214, dt214);
+		Plan newSubPlan3 = vc.findPlan("pistol-monthly", dt3, dt3);
 		
-		dt = new DateTime("2011-02-02T00:00:00+00:00");
-		d = new Date(dt.getMillis() + 1000);
-		vc.configureEffectiveDate(d);
-		assertEquals(dt.toDate(),vc.getEffectiveDate());
+		Assert.assertEquals(newSubPlan1.getAllPhases()[1].getRecurringPrice().getPrice(Currency.USD), new BigDecimal("1.0"));
+		Assert.assertEquals(newSubPlan2.getAllPhases()[1].getRecurringPrice().getPrice(Currency.USD), new BigDecimal("2.0"));
+		Assert.assertEquals(newSubPlan214.getAllPhases()[1].getRecurringPrice().getPrice(Currency.USD), new BigDecimal("2.0"));
+		Assert.assertEquals(newSubPlan3.getAllPhases()[1].getRecurringPrice().getPrice(Currency.USD), new BigDecimal("3.0"));
 		
-		dt = new DateTime("2011-03-03T00:00:00+00:00");
-		d = new Date(dt.getMillis() + 1000);
-		vc.configureEffectiveDate(d);
-		assertEquals(dt.toDate(),vc.getEffectiveDate());
+		// Existing subscription
 		
-	}
+		Plan exSubPlan2 = vc.findPlan("pistol-monthly", dt2, dt1);
+		Plan exSubPlan214 = vc.findPlan("pistol-monthly", dt214, dt1);
+		Plan exSubPlan3 = vc.findPlan("pistol-monthly", dt3, dt1);
+		
+		Assert.assertEquals(exSubPlan2.getAllPhases()[1].getRecurringPrice().getPrice(Currency.USD), new BigDecimal("1.0"));
+		Assert.assertEquals(exSubPlan214.getAllPhases()[1].getRecurringPrice().getPrice(Currency.USD), new BigDecimal("2.0"));
+		Assert.assertEquals(exSubPlan3.getAllPhases()[1].getRecurringPrice().getPrice(Currency.USD), new BigDecimal("2.0"));
 
+		
+	}
 }
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
index fe66528..c21aac1 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
@@ -89,9 +89,9 @@
 				</duration>
 				<billingPeriod>MONTHLY</billingPeriod>
 				<recurringPrice>
-					<price><currency>GBP</currency><value>29.95</value></price>
-					<price><currency>EUR</currency><value>29.95</value></price> 
-					<price><currency>USD</currency><value>29.95</value></price>								
+					<price><currency>GBP</currency><value>1.0</value></price>
+					<price><currency>EUR</currency><value>1.0</value></price> 
+					<price><currency>USD</currency><value>1.0</value></price>								
 				</recurringPrice>
 			</finalPhase>
 		</plan>
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
index 66f2cca..0e650f1 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
@@ -70,6 +70,7 @@
 
 	<plans>
 		<plan name="pistol-monthly">
+			<effectiveDateForExistingSubscriptons>2011-02-14T00:00:00+00:00</effectiveDateForExistingSubscriptons>
 			<product>Pistol</product>
 			<initialPhases>
 				<phase type="TRIAL">
@@ -88,9 +89,9 @@
 				</duration>
 				<billingPeriod>MONTHLY</billingPeriod>
 				<recurringPrice>
-					<price><currency>GBP</currency><value>29.95</value></price>
-					<price><currency>EUR</currency><value>29.95</value></price> 
-					<price><currency>USD</currency><value>29.95</value></price>								
+					<price><currency>GBP</currency><value>2.0</value></price>
+					<price><currency>EUR</currency><value>2.0</value></price> 
+					<price><currency>USD</currency><value>2.0</value></price>								
 				</recurringPrice>
 			</finalPhase>
 		</plan>
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
index 88caefd..f7ae066 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
@@ -89,9 +89,9 @@
 				</duration>
 				<billingPeriod>MONTHLY</billingPeriod>
 				<recurringPrice>
-					<price><currency>GBP</currency><value>29.95</value></price>
-					<price><currency>EUR</currency><value>29.95</value></price> 
-					<price><currency>USD</currency><value>29.95</value></price>								
+					<price><currency>GBP</currency><value>3.0</value></price>
+					<price><currency>EUR</currency><value>3.0</value></price> 
+					<price><currency>USD</currency><value>3.0</value></price>								
 				</recurringPrice>
 			</finalPhase>
 		</plan>

entitlement/pom.xml 21(+21 -0)

diff --git a/entitlement/pom.xml b/entitlement/pom.xml
index 7e97852..a698d45 100644
--- a/entitlement/pom.xml
+++ b/entitlement/pom.xml
@@ -61,6 +61,16 @@
             <artifactId>killbill-util</artifactId>
         </dependency>
         <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-account</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-account</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>joda-time</groupId>
             <artifactId>joda-time</artifactId>
         </dependency>
@@ -108,6 +118,17 @@
                     <groups>setup,fast</groups>
                 </configuration>
             </plugin>
+             <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-jar-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>test-jar</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
         </plugins>
     </build>
     <profiles>
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/MigrationPlanAligner.java b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/MigrationPlanAligner.java
index 4290f73..5730399 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/MigrationPlanAligner.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/MigrationPlanAligner.java
@@ -48,11 +48,11 @@ public class MigrationPlanAligner {
 
         try {
             TimedMigration [] events = null;
-            Plan plan0 = catalogService.getCatalog().findPlan(input[0].getPlanPhaseSpecifer().getProductName(),
-                    input[0].getPlanPhaseSpecifer().getBillingPeriod(), input[0].getPlanPhaseSpecifer().getPriceListName());
+            Plan plan0 = catalogService.getFullCatalog().findPlan(input[0].getPlanPhaseSpecifer().getProductName(),
+                    input[0].getPlanPhaseSpecifer().getBillingPeriod(), input[0].getPlanPhaseSpecifer().getPriceListName(), now);
 
-            Plan plan1 = (input.length > 1) ? catalogService.getCatalog().findPlan(input[1].getPlanPhaseSpecifer().getProductName(),
-                    input[1].getPlanPhaseSpecifer().getBillingPeriod(), input[1].getPlanPhaseSpecifer().getPriceListName()) :
+            Plan plan1 = (input.length > 1) ? catalogService.getFullCatalog().findPlan(input[1].getPlanPhaseSpecifer().getProductName(),
+                    input[1].getPlanPhaseSpecifer().getBillingPeriod(), input[1].getPlanPhaseSpecifer().getPriceListName(), now) :
                         null;
 
             DateTime migrationStartDate = now;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
index 083aef5..2514263 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
@@ -62,9 +62,9 @@ public class PlanAligner  {
      * @throws EntitlementUserApiException
      */
     public TimedPhase [] getCurrentAndNextTimedPhaseOnCreate(SubscriptionData subscription,
-            Plan plan, PhaseType initialPhase, String priceList, DateTime effectiveDate)
+            Plan plan, PhaseType initialPhase, String priceList, DateTime requestedDate, DateTime effectiveDate)
         throws CatalogApiException, EntitlementUserApiException {
-        List<TimedPhase> timedPhases = getTimedPhaseOnCreate(subscription, plan, initialPhase, priceList, effectiveDate);
+        List<TimedPhase> timedPhases = getTimedPhaseOnCreate(subscription, plan, initialPhase, priceList, requestedDate, effectiveDate);
         TimedPhase [] result = new TimedPhase[2];
         result[0] = getTimedPhase(timedPhases, effectiveDate, WhichPhase.CURRENT);
         result[1] = getTimedPhase(timedPhases, effectiveDate, WhichPhase.NEXT);
@@ -84,9 +84,9 @@ public class PlanAligner  {
      * @throws EntitlementUserApiException
      */
     public TimedPhase getCurrentTimedPhaseOnChange(SubscriptionData subscription,
-            Plan plan, String priceList, DateTime effectiveDate)
+            Plan plan, String priceList, DateTime requestedDate, DateTime effectiveDate)
         throws CatalogApiException, EntitlementUserApiException {
-        return getTimedPhaseOnChange(subscription, plan, priceList, effectiveDate, WhichPhase.CURRENT);
+        return getTimedPhaseOnChange(subscription, plan, priceList, requestedDate, effectiveDate, WhichPhase.CURRENT);
     }
 
     /**
@@ -101,9 +101,9 @@ public class PlanAligner  {
      * @throws EntitlementUserApiException
      */
     public TimedPhase getNextTimedPhaseOnChange(SubscriptionData subscription,
-            Plan plan, String priceList, DateTime effectiveDate)
+            Plan plan, String priceList, DateTime requestedDate, DateTime effectiveDate)
         throws CatalogApiException, EntitlementUserApiException {
-        return getTimedPhaseOnChange(subscription, plan, priceList, effectiveDate, WhichPhase.NEXT);
+        return getTimedPhaseOnChange(subscription, plan, priceList, requestedDate, effectiveDate, WhichPhase.NEXT);
     }
 
     /**
@@ -127,10 +127,10 @@ public class PlanAligner  {
     }
 
     private List<TimedPhase> getTimedPhaseOnCreate(SubscriptionData subscription,
-            Plan plan, PhaseType initialPhase, String priceList, DateTime effectiveDate)
+            Plan plan, PhaseType initialPhase, String priceList, DateTime requestedDate, DateTime effectiveDate)
         throws CatalogApiException, EntitlementUserApiException  {
 
-        Catalog catalog = catalogService.getCatalog();
+        Catalog catalog = catalogService.getFullCatalog();
 
         PlanSpecifier planSpecifier = new PlanSpecifier(plan.getProduct().getName(),
                 plan.getProduct().getCategory(),
@@ -139,7 +139,7 @@ public class PlanAligner  {
 
         DateTime planStartDate = null;
         PlanAlignmentCreate alignement = null;
-        alignement = catalog.planCreateAlignment(planSpecifier);
+        alignement = catalog.planCreateAlignment(planSpecifier, requestedDate); 
 
         switch(alignement) {
         case START_OF_SUBSCRIPTION:
@@ -155,10 +155,10 @@ public class PlanAligner  {
     }
 
     private TimedPhase getTimedPhaseOnChange(SubscriptionData subscription,
-            Plan plan, String priceList, DateTime effectiveDate, WhichPhase which)
+            Plan plan, String priceList, DateTime requestedDate, DateTime effectiveDate, WhichPhase which)
         throws CatalogApiException, EntitlementUserApiException {
 
-        Catalog catalog = catalogService.getCatalog();
+        Catalog catalog = catalogService.getFullCatalog();
 
         PlanPhase currentPhase = subscription.getCurrentPhase();
         Plan currentPlan = subscription.getCurrentPlan();
@@ -178,7 +178,7 @@ public class PlanAligner  {
         DateTime planStartDate = null;
 
         PlanAlignmentChange alignment = null;
-        alignment = catalog.planChangeAlignment(fromPlanPhaseSpecifier, toPlanSpecifier);
+        alignment = catalog.planChangeAlignment(fromPlanPhaseSpecifier, toPlanSpecifier, requestedDate);
         switch(alignment) {
         case START_OF_SUBSCRIPTION:
             planStartDate = subscription.getStartDate();
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
index 2753e02..fd130a9 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/billing/DefaultEntitlementBillingApi.java
@@ -23,8 +23,11 @@ import java.util.TreeSet;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.inject.Inject;
+import com.ning.billing.ErrorCode;
 import com.ning.billing.account.api.Account;
 import com.ning.billing.account.api.AccountUserApi;
 import com.ning.billing.catalog.api.BillingAlignment;
@@ -43,7 +46,8 @@ import com.ning.billing.entitlement.api.user.SubscriptionTransition;
 import com.ning.billing.entitlement.engine.dao.EntitlementDao;
 
 public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
-
+	private Logger log = LoggerFactory.getLogger(DefaultEntitlementBillingApi.class);
+	
     private final EntitlementDao dao;
     private final AccountUserApi accountApi;
     private final CatalogService catalogService;
@@ -65,22 +69,23 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
         for (SubscriptionBundle bundle: bundles) {
             subscriptions.addAll(dao.getSubscriptions(bundle.getId()));
         }
-        List<SubscriptionTransition> transitions = new ArrayList<SubscriptionTransition>();
-        for (Subscription subscription: subscriptions) {
-            transitions.addAll(subscription.getAllTransitions());
-        }
-        
-        Account account = accountApi.getAccountById(accountId);
-        
+
         SortedSet<BillingEvent> result = new TreeSet<BillingEvent>();        
-        for (SubscriptionTransition transition : transitions) {
-            result.add(new DefaultBillingEvent(transition, account.getBillCycleDay()));
+        for (Subscription subscription: subscriptions) {
+        	for (SubscriptionTransition transition : subscription.getAllTransitions()) {
+        		try {
+        			result.add(new DefaultBillingEvent(transition, subscription, calculateBCD(transition, accountId)));
+        		} catch (CatalogApiException e) {
+        			log.error("Failing to identify catalog components while creating BillingEvent from transition: " + 
+        					transition.getId().toString(), e);
+        		}
+        	}
         }
         return result;
     }
     
     private int calculateBCD(SubscriptionTransition transition, UUID accountId) throws CatalogApiException {
-    	Catalog catalog = catalogService.getCatalog();
+    	Catalog catalog = catalogService.getFullCatalog();
     	Plan plan = transition.getNextPlan();
     	Product product = plan.getProduct();
     	PlanPhase phase = transition.getNextPhase();
@@ -90,16 +95,28 @@ public class DefaultEntitlementBillingApi implements EntitlementBillingApi {
     					product.getCategory(), 
     					phase.getBillingPeriod(), 
     					transition.getNextPriceList(), 
-    					phase.getPhaseType()));
+    					phase.getPhaseType()), 
+    					transition.getRequestedTransitionTime());
     	int result = 0;
+    	Account account = accountApi.getAccountById(accountId);
     	switch (alignment) {
-    		case ACCOUNT : result = accountApi.getAccountById(accountId).getBillCycleDay();
+    		case ACCOUNT : 
+    			result = account.getBillCycleDay();
     		break;
-    		case BUNDLE : result = dao.getSubscriptionBundleFromId(transition.getBundleId()).getStartDate().getDayOfMonth();
+    		case BUNDLE : 
+    			SubscriptionBundle bundle = dao.getSubscriptionBundleFromId(transition.getBundleId());
+    			//TODO result = bundle.getStartDate().toDateTime(account.getTimeZone()).getDayOfMonth();
+    			result = bundle.getStartDate().getDayOfMonth();
     		break;
-    		case SUBSCRIPTION : result = dao.getSubscriptionFromId(transition.getSubscriptionId()).getStartDate().getDayOfMonth();
+    		case SUBSCRIPTION :
+    			Subscription subscription = dao.getSubscriptionFromId(transition.getSubscriptionId());
+    			//TODO result = subscription.getStartDate().toDateTime(account.getTimeZone()).getDayOfMonth();
+    			result = subscription.getStartDate().getDayOfMonth();
     		break;
     	}
+    	if(result == 0) {
+    		throw new CatalogApiException(ErrorCode.CAT_INVALID_BILLING_ALIGNMENT, alignment.toString());
+    	}
     	return result;
     		
     }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
index 8b6d59a..f54f902 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/DefaultEntitlementUserApi.java
@@ -100,7 +100,7 @@ public class DefaultEntitlementUserApi implements EntitlementUserApi {
             requestedDate = (requestedDate == null) ? now : requestedDate;
             DateTime effectiveDate = requestedDate;
 
-            Plan plan = catalogService.getCatalog().findPlan(spec.getProductName(), spec.getBillingPeriod(), realPriceList);
+            Plan plan = catalogService.getFullCatalog().findPlan(spec.getProductName(), spec.getBillingPeriod(), realPriceList, requestedDate);
 
 
             PlanPhase phase = (plan.getInitialPhases() != null) ? plan.getInitialPhases()[0] : plan.getFinalPhase();
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
index 3aebac0..d2af1a6 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionApiService.java
@@ -60,7 +60,7 @@ public class SubscriptionApiService {
             SubscriptionData subscription = new SubscriptionData(builder, this, clock);
 
 
-            TimedPhase [] curAndNextPhases = planAligner.getCurrentAndNextTimedPhaseOnCreate(subscription, plan, initialPhase, realPriceList, effectiveDate);
+            TimedPhase [] curAndNextPhases = planAligner.getCurrentAndNextTimedPhaseOnCreate(subscription, plan, initialPhase, realPriceList, requestedDate, effectiveDate);
             ApiEventCreate creationEvent = new ApiEventCreate(new ApiEventBuilder()
             .setSubscriptionId(subscription.getId())
             .setEventPlan(plan.getName())
@@ -81,7 +81,7 @@ public class SubscriptionApiService {
                 events.add(nextPhaseEvent);
             }
             dao.createSubscription(subscription, events);
-            subscription.rebuildTransitions(events, catalogService.getCatalog());
+            subscription.rebuildTransitions(events, catalogService.getFullCatalog());
             return subscription;
         } catch (CatalogApiException e) {
             throw new EntitlementUserApiException(e);
@@ -112,7 +112,7 @@ public class SubscriptionApiService {
                     subscription.getCurrentPhase().getPhaseType());
 
             ActionPolicy policy = null;
-            policy = catalogService.getCatalog().planCancelPolicy(planPhase);
+            policy = catalogService.getFullCatalog().planCancelPolicy(planPhase, requestedDate);
             DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, requestedDate);
 
             EntitlementEvent cancelEvent = new ApiEventCancel(new ApiEventBuilder()
@@ -123,7 +123,7 @@ public class SubscriptionApiService {
             .setRequestedDate(now));
 
             dao.cancelSubscription(subscription.getId(), cancelEvent);
-            subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getCatalog());
+            subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getFullCatalog());
         } catch (CatalogApiException e) {
             throw new EntitlementUserApiException(e);
         }
@@ -157,7 +157,7 @@ public class SubscriptionApiService {
             uncancelEvents.add(nextPhaseEvent);
         }
         dao.uncancelSubscription(subscription.getId(), uncancelEvents);
-        subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getCatalog());
+        subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getFullCatalog());
     }
 
     public void changePlan(SubscriptionData subscription, String productName, BillingPeriod term,
@@ -187,7 +187,7 @@ public class SubscriptionApiService {
             PlanChangeResult planChangeResult = null;
             try {
 
-                Product destProduct = catalogService.getCatalog().findProduct(productName);
+                Product destProduct = catalogService.getFullCatalog().findProduct(productName, requestedDate);
                 Plan currentPlan = subscription.getCurrentPlan();
                 PlanPhaseSpecifier fromPlanPhase = new PlanPhaseSpecifier(currentPlan.getProduct().getName(),
                         currentPlan.getProduct().getCategory(),
@@ -198,7 +198,7 @@ public class SubscriptionApiService {
                         term,
                         priceList);
 
-                planChangeResult = catalogService.getCatalog().planChange(fromPlanPhase, toPlanPhase);
+                planChangeResult = catalogService.getFullCatalog().planChange(fromPlanPhase, toPlanPhase, requestedDate);
             } catch (CatalogApiException e) {
                 throw new EntitlementUserApiException(e);
             }
@@ -206,10 +206,10 @@ public class SubscriptionApiService {
             ActionPolicy policy = planChangeResult.getPolicy();
             PriceList newPriceList = planChangeResult.getNewPriceList();
 
-            Plan newPlan = catalogService.getCatalog().findPlan(productName, term, newPriceList.getName());
+            Plan newPlan = catalogService.getFullCatalog().findPlan(productName, term, newPriceList.getName(), requestedDate);
             DateTime effectiveDate = subscription.getPlanChangeEffectiveDate(policy, now);
 
-            TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnChange(subscription, newPlan, newPriceList.getName(), effectiveDate);
+            TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnChange(subscription, newPlan, newPriceList.getName(), requestedDate, effectiveDate);
 
             EntitlementEvent changeEvent = new ApiEventChange(new ApiEventBuilder()
             .setSubscriptionId(subscription.getId())
@@ -221,7 +221,7 @@ public class SubscriptionApiService {
             .setEffectiveDate(effectiveDate)
             .setRequestedDate(now));
 
-            TimedPhase nextTimedPhase = planAligner.getNextTimedPhaseOnChange(subscription, newPlan, newPriceList.getName(), effectiveDate);
+            TimedPhase nextTimedPhase = planAligner.getNextTimedPhaseOnChange(subscription, newPlan, newPriceList.getName(), requestedDate, effectiveDate);
             PhaseEvent nextPhaseEvent = (nextTimedPhase != null) ?
                     PhaseEventData.getNextPhaseEvent(nextTimedPhase.getPhase().getName(), subscription, now, nextTimedPhase.getStartPhase()) :
                         null;
@@ -232,7 +232,7 @@ public class SubscriptionApiService {
                     }
                     changeEvents.add(changeEvent);
                     dao.changePlan(subscription.getId(), changeEvents);
-                    subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getCatalog());
+                    subscription.rebuildTransitions(dao.getEventsForSubscription(subscription.getId()), catalogService.getFullCatalog());
         } catch (CatalogApiException e) {
             throw new EntitlementUserApiException(e);
         }
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 11f6d71..6de8765 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
@@ -342,8 +342,8 @@ public class SubscriptionData implements Subscription {
         String nextPriceList = null;
 
         SubscriptionState previousState = null;
-        String previousPlanName = null;
-        String previousPhaseName = null;
+        //String previousPlanName = null;
+        //String previousPhaseName = null;
         String previousPriceList = null;
 
         transitions = new LinkedList<SubscriptionTransitionData>();
@@ -407,10 +407,8 @@ public class SubscriptionData implements Subscription {
             Plan nextPlan = null;
             PlanPhase nextPhase = null;
             try {
-                previousPlan = (previousPlanName != null) ? catalog.findPlan(previousPlanName) : null;
-                previousPhase = (previousPhaseName != null) ? catalog.findPhase(previousPhaseName) : null;
-                nextPlan = (nextPlanName != null) ? catalog.findPlan(nextPlanName) : null;
-                nextPhase = (nextPhaseName != null) ? catalog.findPhase(nextPhaseName) : null;
+                nextPlan = (nextPlanName != null) ? catalog.findPlan(nextPlanName, cur.getRequestedDate(), getStartDate()) : null;
+                nextPhase = (nextPhaseName != null) ? catalog.findPhase(nextPhaseName, cur.getRequestedDate(), getStartDate()) : null;
             } catch (CatalogApiException e) {
                 log.error(String.format("Failed to build transition for subscription %s", id), e);
             }
@@ -433,8 +431,8 @@ public class SubscriptionData implements Subscription {
             transitions.add(transition);
 
             previousState = nextState;
-            previousPlanName = nextPlanName;
-            previousPhaseName = nextPhaseName;
+            previousPlan = nextPlan;
+            previousPhase = nextPhase;
             previousPriceList = nextPriceList;
         }
     }
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionFactory.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionFactory.java
index 207b4b2..cef1b43 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionFactory.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/SubscriptionFactory.java
@@ -44,7 +44,7 @@ public class SubscriptionFactory {
     public SubscriptionData createSubscription(SubscriptionBuilder builder, List<EntitlementEvent> events) {
         SubscriptionData subscription = new SubscriptionData(builder, apiService, clock);
         if (events.size() > 0) {
-            subscription.rebuildTransitions(events, catalogService.getCatalog());
+            subscription.rebuildTransitions(events, catalogService.getFullCatalog());
         }
         return subscription;
     }
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadAccount.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadAccount.java
new file mode 100644
index 0000000..ff34909
--- /dev/null
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadAccount.java
@@ -0,0 +1,148 @@
+/*
+ * 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.entitlement.api.billing;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.util.customfield.CustomField;
+import com.ning.billing.util.tag.Tag;
+import com.ning.billing.util.tag.TagDescription;
+
+public class BrainDeadAccount implements Account {
+
+	@Override
+	public String getExternalKey() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public String getName() {
+		throw new UnsupportedOperationException();	}
+
+	@Override
+	public int getFirstNameLength() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public String getEmail() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public String getPhone() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public int getBillCycleDay() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public Currency getCurrency() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public String getPaymentProviderName() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public String getFieldValue(String fieldName) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void setFieldValue(String fieldName, String fieldValue) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public List<CustomField> getFieldList() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void clearFields() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public String getObjectName() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public UUID getId() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public List<Tag> getTagList() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public boolean hasTag(String tagName) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void addTag(TagDescription description, String addedBy,
+			DateTime dateAdded) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void addTags(List<Tag> tags) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void clearTags() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void removeTag(TagDescription description) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public boolean generateInvoice() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public boolean processPayment() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public BigDecimal getBalance() {
+		throw new UnsupportedOperationException();
+	}
+
+}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadAccountUserApi.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadAccountUserApi.java
new file mode 100644
index 0000000..5ceaa5b
--- /dev/null
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadAccountUserApi.java
@@ -0,0 +1,58 @@
+/*
+ * 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.entitlement.api.billing;
+
+import java.util.List;
+import java.util.UUID;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.AccountData;
+import com.ning.billing.account.api.AccountUserApi;
+
+public class BrainDeadAccountUserApi implements AccountUserApi {
+
+	@Override
+	public Account createAccount(AccountData data) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void saveAccount(Account account) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public Account getAccountByKey(String key) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public Account getAccountById(UUID accountId) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public List<Account> getAccounts() {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public UUID getIdFromKey(String externalKey) {
+		throw new UnsupportedOperationException();
+	}
+
+}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadMockEntitlementDao.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadMockEntitlementDao.java
new file mode 100644
index 0000000..f7d8186
--- /dev/null
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/BrainDeadMockEntitlementDao.java
@@ -0,0 +1,148 @@
+/*
+ * 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.entitlement.api.billing;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.UUID;
+
+import com.ning.billing.entitlement.api.migration.AccountMigrationData;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
+import com.ning.billing.entitlement.api.user.SubscriptionData;
+import com.ning.billing.entitlement.engine.dao.EntitlementDao;
+import com.ning.billing.entitlement.events.EntitlementEvent;
+
+class BrainDeadMockEntitlementDao implements EntitlementDao {
+
+	@Override
+	public List<SubscriptionBundle> getSubscriptionBundleForAccount(
+			UUID accountId) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public SubscriptionBundle getSubscriptionBundleFromKey(String bundleKey) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public SubscriptionBundle getSubscriptionBundleFromId(UUID bundleId) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public SubscriptionBundle createSubscriptionBundle(
+			SubscriptionBundleData bundle) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public Subscription getSubscriptionFromId(UUID subscriptionId) {
+		throw new UnsupportedOperationException();
+
+	}
+
+	@Override
+	public Subscription getBaseSubscription(UUID bundleId) {
+		throw new UnsupportedOperationException();
+
+	}
+
+	@Override
+	public List<Subscription> getSubscriptions(UUID bundleId) {
+		throw new UnsupportedOperationException();
+
+	}
+
+	@Override
+	public List<Subscription> getSubscriptionsForKey(String bundleKey) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void updateSubscription(SubscriptionData subscription) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void createNextPhaseEvent(UUID subscriptionId,
+			EntitlementEvent nextPhase) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public List<EntitlementEvent> getEventsForSubscription(
+			UUID subscriptionId) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public List<EntitlementEvent> getPendingEventsForSubscription(
+			UUID subscriptionId) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public List<EntitlementEvent> getEventsReady(UUID ownerId,
+			int sequenceId) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void clearEventsReady(UUID ownerId,
+			Collection<EntitlementEvent> cleared) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void createSubscription(SubscriptionData subscription,
+			List<EntitlementEvent> initialEvents) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void cancelSubscription(UUID subscriptionId,
+			EntitlementEvent cancelEvent) {
+		throw new UnsupportedOperationException();
+
+	}
+
+	@Override
+	public void uncancelSubscription(UUID subscriptionId,
+			List<EntitlementEvent> uncancelEvents) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void changePlan(UUID subscriptionId,
+			List<EntitlementEvent> changeEvents) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void migrate(UUID acountId, AccountMigrationData data) {
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void undoMigration(UUID accountId) {
+		throw new UnsupportedOperationException();
+	}
+	
+}
\ No newline at end of file
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultEntitlementBillingApi.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultEntitlementBillingApi.java
new file mode 100644
index 0000000..08b05d6
--- /dev/null
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/billing/TestDefaultEntitlementBillingApi.java
@@ -0,0 +1,281 @@
+/*
+ * 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.entitlement.api.billing;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.testng.Assert;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+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.api.CatalogApiException;
+import com.ning.billing.catalog.api.CatalogService;
+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.catalog.api.PriceListSet;
+import com.ning.billing.catalog.glue.CatalogModule;
+import com.ning.billing.entitlement.api.TestApiBase;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.Subscription.SubscriptionState;
+import com.ning.billing.entitlement.api.user.SubscriptionBundle;
+import com.ning.billing.entitlement.api.user.SubscriptionBundleData;
+import com.ning.billing.entitlement.api.user.SubscriptionData;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
+import com.ning.billing.entitlement.api.user.SubscriptionTransition;
+import com.ning.billing.entitlement.api.user.SubscriptionTransitionData;
+import com.ning.billing.entitlement.engine.dao.EntitlementDao;
+import com.ning.billing.entitlement.events.EntitlementEvent.EventType;
+import com.ning.billing.entitlement.events.user.ApiEventType;
+import com.ning.billing.lifecycle.KillbillService.ServiceException;
+import com.ning.billing.util.clock.Clock;
+import com.ning.billing.util.clock.DefaultClock;
+
+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);
+	
+	private CatalogService catalogService;
+	private ArrayList<SubscriptionBundle> bundles;
+	private ArrayList<Subscription> subscriptions;
+	private ArrayList<SubscriptionTransition> transitions;
+	private BrainDeadMockEntitlementDao dao;
+
+	private Clock clock;
+	private SubscriptionData subscription;
+	private DateTime subscriptionStartDate;
+
+	@BeforeClass(groups={"setup"})
+	public void setup() throws ServiceException {
+		TestApiBase.loadSystemPropertiesFromClasspath("/entitlement.properties");
+        final Injector g = Guice.createInjector(Stage.PRODUCTION, new CatalogModule(), new AbstractModule() {
+			protected void configure() {
+				 bind(Clock.class).to(DefaultClock.class).asEagerSingleton();
+			}  	
+        });
+
+        
+        catalogService = g.getInstance(CatalogService.class);
+        clock = g.getInstance(Clock.class);
+        
+        ((DefaultCatalogService)catalogService).loadCatalog();
+	}
+	
+	@BeforeMethod
+	public void setupEveryTime() {
+		bundles = new ArrayList<SubscriptionBundle>();
+		final SubscriptionBundle bundle = new SubscriptionBundleData( zeroId,"TestKey", oneId,  new DateTime().minusDays(4));
+		bundles.add(bundle);
+		
+		
+		transitions = new ArrayList<SubscriptionTransition>();
+		
+		
+		subscriptions = new ArrayList<Subscription>();
+		
+		SubscriptionBuilder builder = new SubscriptionBuilder();
+		subscriptionStartDate = new DateTime().minusDays(3);
+		builder.setStartDate(subscriptionStartDate);
+		subscription = new SubscriptionData(builder) {
+		    public List<SubscriptionTransition> getAllTransitions() {
+		    	return transitions;
+		    }
+		};
+
+		subscriptions.add(subscription);
+		
+		dao = new BrainDeadMockEntitlementDao() {
+			public List<SubscriptionBundle> getSubscriptionBundleForAccount(
+					UUID accountId) {
+				return bundles;
+				
+			}
+
+			public List<Subscription> getSubscriptions(UUID bundleId) {
+				return subscriptions;
+			}
+
+			public Subscription getSubscriptionFromId(UUID subscriptionId) {
+				return subscription;
+
+			}
+			
+			@Override
+			public SubscriptionBundle getSubscriptionBundleFromId(UUID bundleId) {
+				return bundle;
+			}
+
+
+		};
+
+	}
+	
+	@Test
+	public void testBillingEventsEmpty() {
+		EntitlementDao dao = new BrainDeadMockEntitlementDao() {
+			public List<SubscriptionBundle> getSubscriptionBundleForAccount(
+					UUID accountId) {
+				return new ArrayList<SubscriptionBundle>();
+			}
+			
+		};
+		AccountUserApi accountApi = new BrainDeadAccountUserApi() ;
+		DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(dao,accountApi,catalogService);
+		SortedSet<BillingEvent> events = api.getBillingEventsForAccount(new UUID(0L,0L));
+		Assert.assertEquals(events.size(), 0);
+	}
+	
+	@Test
+	public void testBillingEventsNoBillingPeriod() throws CatalogApiException {
+		DateTime now = clock.getUTCNow();
+		DateTime then = now.minusDays(1);
+		Plan nextPlan = catalogService.getFullCatalog().findPlan("shotgun-annual", now);
+		PlanPhase nextPhase = nextPlan.getAllPhases()[0]; // The trial has no billing period
+		String nextPriceList = PriceListSet.DEFAULT_PRICELIST_NAME;
+		SubscriptionTransition t = new SubscriptionTransitionData(
+				zeroId, oneId, twoId, EventType.API_USER, ApiEventType.CREATE, then, now, null, null, null, null, SubscriptionState.ACTIVE, nextPlan, nextPhase, nextPriceList);
+		transitions.add(t);
+		
+		AccountUserApi accountApi = new BrainDeadAccountUserApi(){
+
+			@Override
+			public Account getAccountById(UUID accountId) {
+				return new BrainDeadAccount(){@Override
+				public int getBillCycleDay() {
+					return 32;
+				}};
+			}} ;
+		DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(dao,accountApi,catalogService);
+		SortedSet<BillingEvent> events = api.getBillingEventsForAccount(new UUID(0L,0L));
+		checkFirstEvent(events, nextPlan, 32, oneId, now, nextPhase, ApiEventType.CREATE.toString());
+	}
+
+	@Test
+	public void testBillingEventsAnual() throws CatalogApiException {
+		DateTime now = clock.getUTCNow();
+		DateTime then = now.minusDays(1);
+		Plan nextPlan = catalogService.getFullCatalog().findPlan("shotgun-annual", now);
+		PlanPhase nextPhase = nextPlan.getAllPhases()[1];
+		String nextPriceList = PriceListSet.DEFAULT_PRICELIST_NAME;
+		SubscriptionTransition t = new SubscriptionTransitionData(
+				zeroId, oneId, twoId, EventType.API_USER, ApiEventType.CREATE, then, now, null, null, null, null, SubscriptionState.ACTIVE, nextPlan, nextPhase, nextPriceList);
+		transitions.add(t);
+		
+		AccountUserApi accountApi = new BrainDeadAccountUserApi(){
+
+			@Override
+			public Account getAccountById(UUID accountId) {
+				return new BrainDeadAccount(){@Override
+				public int getBillCycleDay() {
+					return 1;
+				}};
+			}} ;
+		DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(dao,accountApi,catalogService);
+		SortedSet<BillingEvent> events = api.getBillingEventsForAccount(new UUID(0L,0L));
+		checkFirstEvent(events, nextPlan, subscription.getStartDate().getDayOfMonth(), oneId, now, nextPhase, ApiEventType.CREATE.toString());
+	}
+	
+	@Test
+	public void testBillingEventsMonthly() throws CatalogApiException {
+		DateTime now = clock.getUTCNow();
+		DateTime then = now.minusDays(1);
+		Plan nextPlan = catalogService.getFullCatalog().findPlan("shotgun-annual", now);
+		PlanPhase nextPhase = nextPlan.getAllPhases()[1];
+		String nextPriceList = PriceListSet.DEFAULT_PRICELIST_NAME;
+		SubscriptionTransition t = new SubscriptionTransitionData(
+				zeroId, oneId, twoId, EventType.API_USER, ApiEventType.CREATE, then, now, null, null, null, null, SubscriptionState.ACTIVE, nextPlan, nextPhase, nextPriceList);
+		transitions.add(t);
+		
+		AccountUserApi accountApi = new BrainDeadAccountUserApi(){
+
+			@Override
+			public Account getAccountById(UUID accountId) {
+				return new BrainDeadAccount(){@Override
+				public int getBillCycleDay() {
+					return 32;
+				}};
+			}} ;
+		DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(dao,accountApi,catalogService);
+		SortedSet<BillingEvent> events = api.getBillingEventsForAccount(new UUID(0L,0L));
+		checkFirstEvent(events, nextPlan, 32, oneId, now, nextPhase, ApiEventType.CREATE.toString());
+	}
+	
+	@Test
+	public void testBillingEventsAddOn() throws CatalogApiException {
+		DateTime now = clock.getUTCNow();
+		DateTime then = now.minusDays(1);
+		Plan nextPlan = catalogService.getFullCatalog().findPlan("shotgun-annual", now);
+		PlanPhase nextPhase = nextPlan.getAllPhases()[0];
+		String nextPriceList = PriceListSet.DEFAULT_PRICELIST_NAME;
+		SubscriptionTransition t = new SubscriptionTransitionData(
+				zeroId, oneId, twoId, EventType.API_USER, ApiEventType.CREATE, then, now, null, null, null, null, SubscriptionState.ACTIVE, nextPlan, nextPhase, nextPriceList);
+		transitions.add(t);
+		
+		AccountUserApi accountApi = new BrainDeadAccountUserApi(){
+
+			@Override
+			public Account getAccountById(UUID accountId) {
+				return new BrainDeadAccount(){@Override
+				public int getBillCycleDay() {
+					return 1;
+				}};
+			}} ;
+		DefaultEntitlementBillingApi api = new DefaultEntitlementBillingApi(dao,accountApi,catalogService);
+		SortedSet<BillingEvent> events = api.getBillingEventsForAccount(new UUID(0L,0L));
+		checkFirstEvent(events, nextPlan, bundles.get(0).getStartDate().getDayOfMonth(), oneId, now, nextPhase, ApiEventType.CREATE.toString());
+	}
+
+
+	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();
+		if(nextPhase.getFixedPrice() != null) {
+			Assert.assertEquals(nextPhase.getFixedPrice().getPrice(Currency.USD), event.getFixedPrice().getPrice(Currency.USD));
+		}
+		if(nextPhase.getRecurringPrice() != null) {
+			Assert.assertEquals(nextPhase.getRecurringPrice().getPrice(Currency.USD), event.getRecurringPrice().getPrice(Currency.USD));
+		}
+		
+		Assert.assertEquals(BCD, event.getBillCycleDay());
+		Assert.assertEquals(id, event.getSubscription().getId());
+		Assert.assertEquals(time, event.getEffectiveDate());
+		Assert.assertEquals(nextPhase, event.getPlanPhase());
+		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(nextPhase.getFixedPrice(), event.getFixedPrice());
+		Assert.assertEquals(nextPhase.getRecurringPrice(), event.getRecurringPrice());
+	}
+	
+	
+}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
index ff3a443..7f8e88a 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/TestApiBase.java
@@ -147,7 +147,7 @@ public abstract class TestApiBase {
         accountData = getAccountData();
         assertNotNull(accountData);
 
-        catalog = catalogService.getCatalog();
+        catalog = catalogService.getFullCatalog();
         assertNotNull(catalog);
 
 
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
index ff55ca0..d5546d7 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
@@ -23,6 +23,8 @@ import static org.testng.Assert.assertTrue;
 
 import java.util.List;
 import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.testng.Assert;
 
 import com.ning.billing.catalog.api.BillingPeriod;
@@ -38,7 +40,7 @@ import com.ning.billing.entitlement.events.phase.PhaseEvent;
 import com.ning.billing.util.clock.DefaultClock;
 
 public abstract class TestUserApiCreate extends TestApiBase {
-
+	Logger log = LoggerFactory.getLogger(TestUserApiCreate.class);
 
     public void testCreateWithRequestedDate() {
         log.info("Starting testCreateWithRequestedDate");
@@ -68,6 +70,7 @@ public abstract class TestUserApiCreate extends TestApiBase {
             assertTrue(testListener.isCompleted(5000));
 
         } catch (EntitlementUserApiException e) {
+        	log.error("Unexpected exception",e);
             Assert.fail(e.getMessage());
         }
     }
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
index c32b654..e485420 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiError.java
@@ -49,17 +49,16 @@ public class TestUserApiError extends TestApiBase {
     @Test(enabled=true)
     public void testCreateSubscriptionBadCatalog() {
         // WRONG PRODUTCS
-        tCreateSubscriptionInternal(bundle.getId(), null, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.CAT_NO_SUCH_PRODUCT);
+        tCreateSubscriptionInternal(bundle.getId(), null, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.CAT_NULL_PRODUCT_NAME);
         tCreateSubscriptionInternal(bundle.getId(), "Whatever", BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.CAT_NO_SUCH_PRODUCT);
 
 
         // TODO: MARTIN TO FIX WITH CORRECT ERROR CODE. RIGHT NOW NPE
 
         // WRONG BILLING PERIOD
-        //tCreateSubscriptionInternal(bundle.getId(), "Shotgun", null, IPriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.);
+        tCreateSubscriptionInternal(bundle.getId(), "Shotgun", null, PriceListSet.DEFAULT_PRICELIST_NAME, ErrorCode.CAT_PLAN_NOT_FOUND);
         // WRONG PLAN SET
-        //tCreateSubscriptionInternal(bundle.getId(), "Shotgun", BillingPeriod.ANNUAL, null, ErrorCode.);
-        //tCreateSubscriptionInternal(bundle.getId(), "Shotgun", BillingPeriod.ANNUAL, "Whatever", ErrorCode.);
+        tCreateSubscriptionInternal(bundle.getId(), "Shotgun", BillingPeriod.ANNUAL, "Whatever", ErrorCode.CAT_PRICE_LIST_NOT_FOUND);
 
     }
 
@@ -90,7 +89,7 @@ public class TestUserApiError extends TestApiBase {
             entitlementApi.createSubscription(bundleId,
                     getProductSpecifier(productName, planSet, term, null),
                     clock.getUTCNow());
-            assertFalse(true);
+            Assert.fail("Exception expected, error code: " + expected);
         } catch (EntitlementUserApiException e) {
             assertEquals(e.getCode(), expected.getCode());
             try {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModule.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModule.java
index dc422a6..4a44942 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModule.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/MockEngineModule.java
@@ -16,6 +16,7 @@
 
 package com.ning.billing.entitlement.glue;
 
+import com.ning.billing.account.glue.AccountModuleMock;
 import com.ning.billing.catalog.glue.CatalogModule;
 import com.ning.billing.util.clock.Clock;
 import com.ning.billing.util.clock.ClockMock;
@@ -33,6 +34,7 @@ public class MockEngineModule extends EntitlementModule {
         super.configure();
         install(new EventBusModule());
         install(new CatalogModule());
+        install(new AccountModuleMock());
     }
 
 }
diff --git a/entitlement/src/test/resources/testInput.xml b/entitlement/src/test/resources/testInput.xml
index 01d7cb4..ce3b250 100644
--- a/entitlement/src/test/resources/testInput.xml
+++ b/entitlement/src/test/resources/testInput.xml
@@ -39,7 +39,7 @@ Use Cases to do:
 <catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 	xsi:noNamespaceSchemaLocation="CatalogSchema.xsd ">
 
-	<effectiveDate>2011-10-08T00:00:00+00:00</effectiveDate>
+	<effectiveDate>2011-01-01T00:00:00+00:00</effectiveDate>
 	<catalogName>Firearms</catalogName>
 
 	<currencies>
@@ -162,16 +162,16 @@ Use Cases to do:
 			</createAlignmentCase>
 		</createAlignment>
 		<billingAlignment>
-		<billingAlignmentCase>
-			<alignment>ACCOUNT</alignment>
-		</billingAlignmentCase>
+			<billingAlignmentCase>
+				<productCategory>ADD_ON</productCategory>
+				<alignment>BUNDLE</alignment>
+			</billingAlignmentCase>
 			<billingAlignmentCase>
 				<billingPeriod>ANNUAL</billingPeriod>
 				<alignment>SUBSCRIPTION</alignment>
 			</billingAlignmentCase>
 			<billingAlignmentCase>
-				<productCategory>ADD_ON</productCategory>
-				<alignment>BUNDLE</alignment>
+				<alignment>ACCOUNT</alignment>
 			</billingAlignmentCase>
 		</billingAlignment>
 		<priceList>

invoice/pom.xml 15(+15 -0)

diff --git a/invoice/pom.xml b/invoice/pom.xml
index 3d7dc27..2434c2d 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -35,6 +35,21 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-entitlement</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-catalog</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-catalog</artifactId>
+            <type>test-jar</type>
+            <scope>test</scope>
+        </dependency>
+        
+        <dependency>
             <groupId>org.testng</groupId>
             <artifactId>testng</artifactId>
             <scope>test</scope>
diff --git a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
index 142210b..3b9311e 100644
--- a/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
+++ b/invoice/src/main/java/com/ning/billing/invoice/model/DefaultInvoiceGenerator.java
@@ -103,7 +103,7 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
             BillingEvent thisEvent = events.get(i);
             BillingEvent nextEvent = events.get(i + 1);
 
-            if (thisEvent.getSubscriptionId() == nextEvent.getSubscriptionId()) {
+            if (thisEvent.getSubscription().getId() == nextEvent.getSubscription().getId()) {
                 processEvents(invoiceId, thisEvent, nextEvent, items, targetDate, targetCurrency);
             } else {
                 processEvent(invoiceId, thisEvent, items, targetDate, targetCurrency);
@@ -152,7 +152,7 @@ public class DefaultInvoiceGenerator implements InvoiceGenerator {
 
     private void addInvoiceItem(UUID invoiceId, List<InvoiceItem> items, BillingEvent event, DateTime billThroughDate, BigDecimal amount, BigDecimal rate, Currency currency) {
         if (!(amount.compareTo(BigDecimal.ZERO) == 0)) {
-            DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, event.getSubscriptionId(), event.getEffectiveDate(), billThroughDate, event.getDescription(), amount, rate, currency);
+            DefaultInvoiceItem item = new DefaultInvoiceItem(invoiceId, event.getSubscription().getId(), event.getEffectiveDate(), billThroughDate, event.getDescription(), amount, rate, currency);
             items.add(item);
         }
     }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java b/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
index 8321daf..5d36d55 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/DefaultInvoiceGeneratorTests.java
@@ -25,11 +25,17 @@ import java.util.UUID;
 import org.joda.time.DateTime;
 import org.testng.annotations.Test;
 
+import com.ning.billing.catalog.MockCatalog;
 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.billing.DefaultBillingEvent;
+import com.ning.billing.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.api.user.SubscriptionData;
+import com.ning.billing.entitlement.api.user.SubscriptionFactory.SubscriptionBuilder;
 import com.ning.billing.invoice.api.BillingEventSet;
 import com.ning.billing.invoice.api.Invoice;
 import com.ning.billing.invoice.api.InvoiceItem;
@@ -69,11 +75,13 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     public void testWithSingleMonthlyEvent() {
         BillingEventSet events = new BillingEventSet();
 
-        UUID subscriptionId = UUID.randomUUID();
+        Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
         DateTime startDate = buildDateTime(2011, 9, 1);
-        String planName = "World Domination";
-        String phaseName = "Build Space Laser";
-        BillingEvent event = new DefaultBillingEvent(subscriptionId, startDate, planName, phaseName,
+        MockCatalog catalog = new MockCatalog();
+        Plan plan = catalog.getCurrentPlans()[0];
+        PlanPhase phase = plan.getAllPhases()[0];
+        
+        BillingEvent event = new DefaultBillingEvent(sub, startDate, plan, phase,
                 new InternationalPriceMock(ZERO),new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
                                                1, BillingModeType.IN_ADVANCE, "Test");
         events.add(event);
@@ -93,12 +101,13 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     public void testWithSingleMonthlyEventWithLeadingProRation() {
         BillingEventSet events = new BillingEventSet();
 
-        UUID subscriptionId = UUID.randomUUID();
+        Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
         DateTime startDate = buildDateTime(2011, 9, 1);
-        String planName = "World Domination";
-        String phaseName = "Build Space Laser";
+        MockCatalog catalog = new MockCatalog();
+        Plan plan = catalog.getCurrentPlans()[0];
+        PlanPhase phase = plan.getAllPhases()[0];
         BigDecimal rate = TEN;
-        BillingEvent event = new DefaultBillingEvent(subscriptionId, startDate, planName, phaseName,
+        BillingEvent event = new DefaultBillingEvent(sub, startDate, plan, phase,
                 new InternationalPriceMock(ZERO), new InternationalPriceMock(rate), BillingPeriod.MONTHLY,
                                                15, BillingModeType.IN_ADVANCE,"Test");
         events.add(event);
@@ -122,14 +131,22 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     public void testTwoMonthlySubscriptionsWithAlignedBillingDates() {
         BillingEventSet events = new BillingEventSet();
 
-        BillingEvent event1 = new DefaultBillingEvent(UUID.randomUUID(), buildDateTime(2011, 9, 1),
-                                               "World Domination", "Build Space Laser",
+        MockCatalog catalog = new MockCatalog();
+        Plan plan1 = catalog.getCurrentPlans()[0];
+        PlanPhase phase1 = plan1.getAllPhases()[0];
+        Plan plan2 = catalog.getCurrentPlans()[1];
+        PlanPhase phase2 = plan2.getAllPhases()[0];
+        
+        Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
+
+        BillingEvent event1 = new DefaultBillingEvent(sub, buildDateTime(2011, 9, 1),
+                                               plan1,phase1,
                                                new InternationalPriceMock(ZERO), new InternationalPriceMock(FIVE), BillingPeriod.MONTHLY,
                                                1, BillingModeType.IN_ADVANCE, "Test");
         events.add(event1);
 
-        BillingEvent event2 = new DefaultBillingEvent(UUID.randomUUID(), buildDateTime(2011, 10, 1),
-                                               "Groceries", "Pick Up Milk",
+        BillingEvent event2 = new DefaultBillingEvent(sub, buildDateTime(2011, 10, 1),
+                                               plan2,phase2,
                                                new InternationalPriceMock(ZERO), new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
                                                1, BillingModeType.IN_ADVANCE,"Test");
         events.add(event2);
@@ -148,15 +165,20 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     public void testOnePlan_TwoMonthlyPhases_ChangeImmediate() {
         BillingEventSet events = new BillingEventSet();
 
-        UUID subscriptionId = UUID.randomUUID();
-        BillingEvent event1 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 9, 1),
-                                               "World Domination", "Build Space Laser",
+        MockCatalog catalog = new MockCatalog();
+        Plan plan1 = catalog.getCurrentPlans()[0];
+        PlanPhase phase1 = plan1.getAllPhases()[0];
+
+        
+        Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
+        BillingEvent event1 = new DefaultBillingEvent(sub, buildDateTime(2011, 9, 1),
+                                               plan1,phase1,
                                                new InternationalPriceMock(ZERO),new InternationalPriceMock(FIVE), BillingPeriod.MONTHLY,
                                                1, BillingModeType.IN_ADVANCE,"Test");
         events.add(event1);
 
-        BillingEvent event2 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 10, 15),
-                                               "World Domination", "Incinerate James Bond",
+        BillingEvent event2 = new DefaultBillingEvent(sub, buildDateTime(2011, 10, 15),
+                                               plan1,phase1, //technically should be a different phase but it doesn't impact the test
                                                new InternationalPriceMock(ZERO),new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
                                                15, BillingModeType.IN_ADVANCE,"Test");
         events.add(event2);
@@ -186,21 +208,26 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     public void testOnePlan_ThreeMonthlyPhases_ChangeEOT() {
         BillingEventSet events = new BillingEventSet();
 
-        UUID subscriptionId = UUID.randomUUID();
-        BillingEvent event1 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 9, 1),
-                                               "World Domination", "Build Space Laser",
+        MockCatalog catalog = new MockCatalog();
+        Plan plan1 = catalog.getCurrentPlans()[0];
+        PlanPhase phase1 = plan1.getAllPhases()[0];
+
+
+        Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
+        BillingEvent event1 = new DefaultBillingEvent(sub, buildDateTime(2011, 9, 1),
+        										plan1,phase1,
                                                new InternationalPriceMock(ZERO),new InternationalPriceMock(FIVE), BillingPeriod.MONTHLY,
                                                1, BillingModeType.IN_ADVANCE,"Test");
         events.add(event1);
 
-        BillingEvent event2 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 10, 1),
-                                               "World Domination", "Incinerate James Bond",
+        BillingEvent event2 = new DefaultBillingEvent(sub, buildDateTime(2011, 10, 1),
+												plan1,phase1, //technically should be a different phase but it doesn't impact the test
                                                new InternationalPriceMock(ZERO),new InternationalPriceMock(TEN), BillingPeriod.MONTHLY,
                                                1, BillingModeType.IN_ADVANCE,"Test");
         events.add(event2);
 
-        BillingEvent event3 = new DefaultBillingEvent(subscriptionId, buildDateTime(2011, 11, 1),
-                                               "World Domination", "Cackle Gleefully",
+        BillingEvent event3 = new DefaultBillingEvent(sub, buildDateTime(2011, 11, 1),
+												plan1,phase1, //technically should be a different phase but it doesn't impact the test
                                                new InternationalPriceMock(ZERO),new InternationalPriceMock(THIRTY), BillingPeriod.MONTHLY,
                                                1, BillingModeType.IN_ADVANCE,"Test");
         events.add(event3);
@@ -219,18 +246,22 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
     public void testSingleEventWithExistingInvoice() {
         BillingEventSet events = new BillingEventSet();
 
-        UUID subscriptionId = UUID.randomUUID();
+        Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
         DateTime startDate = buildDateTime(2011, 9, 1);
-
+        
+        MockCatalog catalog = new MockCatalog();
+        Plan plan1 = catalog.getCurrentPlans()[0];
+        PlanPhase phase1 = plan1.getAllPhases()[0];
+        
         BigDecimal rate = FIVE;
-        BillingEvent event1 = new DefaultBillingEvent(subscriptionId, startDate,
-                                               "World Domination", "Build Space Laser",
+        BillingEvent event1 = new DefaultBillingEvent(sub, startDate,
+        										plan1,phase1,
                                                new InternationalPriceMock(ZERO),new InternationalPriceMock(rate), BillingPeriod.MONTHLY,
                                                1, BillingModeType.IN_ADVANCE,"Test");
         events.add(event1);
 
         InvoiceItemList existingInvoiceItems = new InvoiceItemList();
-        InvoiceItem invoiceItem = new DefaultInvoiceItem(UUID.randomUUID(), subscriptionId, startDate, buildDateTime(2012, 1, 1), "",
+        InvoiceItem invoiceItem = new DefaultInvoiceItem(UUID.randomUUID(), sub.getId(), startDate, buildDateTime(2012, 1, 1), "",
                                                  rate.multiply(FOUR), rate, Currency.USD);
         existingInvoiceItems.add(invoiceItem);
 
@@ -397,14 +428,22 @@ public class DefaultInvoiceGeneratorTests extends InvoicingTestBase {
 
     private DefaultBillingEvent createBillingEvent(UUID subscriptionId, DateTime startDate, String planName, String planPhaseName,
                                             BigDecimal rate, int billCycleDay) {
-        return new DefaultBillingEvent(subscriptionId, startDate, planName, planPhaseName,
+        MockCatalog catalog = new MockCatalog();
+        Plan plan = catalog.getCurrentPlans()[0];
+        PlanPhase phase = plan.getAllPhases()[0];
+        Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
+        return new DefaultBillingEvent(sub, startDate, plan, phase,
                 new InternationalPriceMock(ZERO),new InternationalPriceMock(rate), BillingPeriod.MONTHLY,
                                 billCycleDay, BillingModeType.IN_ADVANCE,"Test");
     }
 
     private DefaultBillingEvent createAnnualBillingEvent(UUID subscriptionId, DateTime startDate, String planName, String planPhaseName,
                                                   BigDecimal rate, int billCycleDay) {
-        return new DefaultBillingEvent(subscriptionId, startDate, planName, planPhaseName,
+        MockCatalog catalog = new MockCatalog();
+        Plan plan = catalog.getCurrentPlans()[0];
+        PlanPhase phase = plan.getAllPhases()[0];
+        Subscription sub = new SubscriptionData(new SubscriptionBuilder().setId(UUID.randomUUID()));
+        return new DefaultBillingEvent(sub, startDate, plan, phase,
                 new InternationalPriceMock(ZERO),new InternationalPriceMock(rate), BillingPeriod.ANNUAL,
                                 billCycleDay, BillingModeType.IN_ADVANCE,"Test");
     }
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/InternationalPriceMock.java b/invoice/src/test/java/com/ning/billing/invoice/tests/InternationalPriceMock.java
index 9198ba0..8577544 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/InternationalPriceMock.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/InternationalPriceMock.java
@@ -16,14 +16,13 @@
 
 package com.ning.billing.invoice.tests;
 
-import com.ning.billing.catalog.api.Currency;
-import com.ning.billing.catalog.api.InternationalPrice;
-import com.ning.billing.catalog.api.Price;
+import static org.testng.Assert.fail;
 
 import java.math.BigDecimal;
-import java.util.Date;
 
-import static org.testng.Assert.fail;
+import com.ning.billing.catalog.api.Currency;
+import com.ning.billing.catalog.api.InternationalPrice;
+import com.ning.billing.catalog.api.Price;
 
 public class InternationalPriceMock implements InternationalPrice {
     private final BigDecimal rate;
@@ -44,8 +43,4 @@ public class InternationalPriceMock implements InternationalPrice {
         return rate;
     }
 
-	@Override
-	public Date getEffectiveDateForExistingSubscriptons() {
-		return new Date();
-	}
 }

pom.xml 14(+14 -0)

diff --git a/pom.xml b/pom.xml
index f64b324..21739e9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -61,6 +61,13 @@
             </dependency>
             <dependency>
                 <groupId>com.ning.billing</groupId>
+                <artifactId>killbill-account</artifactId>
+                <version>${project.version}</version>
+                <type>test-jar</type>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>com.ning.billing</groupId>
                 <artifactId>killbill-entitlement</artifactId>
                 <version>${project.version}</version>
             </dependency>
@@ -71,6 +78,13 @@
             </dependency>
             <dependency>
                 <groupId>com.ning.billing</groupId>
+                <artifactId>killbill-catalog</artifactId>
+                <version>${project.version}</version>
+                <type>test-jar</type>
+                <scope>test</scope>
+            </dependency>
+            <dependency>
+                <groupId>com.ning.billing</groupId>
                 <artifactId>killbill-util</artifactId>
                 <version>${project.version}</version>
                 <type>test-jar</type>