killbill-memoizeit

Details

diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithCatalogPlugin.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithCatalogPlugin.java
index 5fe80e5..03dbfb1 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithCatalogPlugin.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithCatalogPlugin.java
@@ -34,31 +34,15 @@ import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.catalog.StandaloneCatalog;
 import org.killbill.billing.catalog.StandaloneCatalogWithPriceOverride;
 import org.killbill.billing.catalog.VersionedCatalog;
-import org.killbill.billing.catalog.api.BillingActionPolicy;
-import org.killbill.billing.catalog.api.BillingAlignment;
-import org.killbill.billing.catalog.api.BillingMode;
 import org.killbill.billing.catalog.api.BillingPeriod;
 import org.killbill.billing.catalog.api.CatalogApiException;
-import org.killbill.billing.catalog.api.Currency;
-import org.killbill.billing.catalog.api.PhaseType;
 import org.killbill.billing.catalog.api.Plan;
-import org.killbill.billing.catalog.api.PlanAlignmentChange;
-import org.killbill.billing.catalog.api.PlanAlignmentCreate;
 import org.killbill.billing.catalog.api.PriceList;
 import org.killbill.billing.catalog.api.Product;
 import org.killbill.billing.catalog.api.ProductCategory;
-import org.killbill.billing.catalog.api.Unit;
-import org.killbill.billing.catalog.api.rules.Case;
-import org.killbill.billing.catalog.api.rules.CaseBillingAlignment;
-import org.killbill.billing.catalog.api.rules.CaseCancelPolicy;
-import org.killbill.billing.catalog.api.rules.CaseChange;
-import org.killbill.billing.catalog.api.rules.CaseChangePlanAlignment;
-import org.killbill.billing.catalog.api.rules.CaseChangePlanPolicy;
-import org.killbill.billing.catalog.api.rules.CaseCreateAlignment;
-import org.killbill.billing.catalog.api.rules.CasePhase;
-import org.killbill.billing.catalog.api.rules.CasePriceList;
-import org.killbill.billing.catalog.api.rules.PlanRules;
 import org.killbill.billing.catalog.override.PriceOverride;
+import org.killbill.billing.catalog.plugin.TestModelStandalonePluginCatalog;
+import org.killbill.billing.catalog.plugin.TestModelVersionedPluginCatalog;
 import org.killbill.billing.catalog.plugin.api.StandalonePluginCatalog;
 import org.killbill.billing.catalog.plugin.api.VersionedPluginCatalog;
 import org.killbill.billing.entitlement.api.DefaultEntitlement;
@@ -74,7 +58,6 @@ import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Function;
-import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.io.Resources;
@@ -142,7 +125,7 @@ public class TestWithCatalogPlugin extends TestIntegrationBase {
 
         @Override
         public VersionedPluginCatalog getVersionedPluginCatalog(final Iterable<PluginProperty> properties, final TenantContext tenantContext) {
-            return new TestVersionedPluginCatalog(versionedCatalog.getCatalogName(), versionedCatalog.getRecurringBillingMode(), toStandalonePluginCatalogs(versionedCatalog.getVersions()));
+            return new TestModelVersionedPluginCatalog(versionedCatalog.getCatalogName(), versionedCatalog.getRecurringBillingMode(), toStandalonePluginCatalogs(versionedCatalog.getVersions()));
         }
 
         private Iterable<StandalonePluginCatalog> toStandalonePluginCatalogs(final List<StandaloneCatalogWithPriceOverride> input) {
@@ -150,584 +133,24 @@ public class TestWithCatalogPlugin extends TestIntegrationBase {
                 @Override
                 public StandalonePluginCatalog apply(final StandaloneCatalogWithPriceOverride input) {
                     try {
-                        return new TestStandalonePluginCatalog(new DateTime(input.getEffectiveDate()),
-                                                               ImmutableList.copyOf(input.getCurrentSupportedCurrencies()),
-                                                               ImmutableList.<Product>copyOf(input.getCurrentProducts()),
-                                                               ImmutableList.<Plan>copyOf(input.getCurrentPlans()),
-                                                               input.getStandaloneCatalog().getPriceLists().getDefaultPricelist(),
-                                                               ImmutableList.<PriceList>copyOf(input.getStandaloneCatalog().getPriceLists().getChildPriceLists()),
-                                                               input.getStandaloneCatalog().getPlanRules(),
-                                                               null /*ImmutableList.<Unit>copyOf(input.getStandaloneCatalog().getCurrentUnits()) */);
+
+                        return new TestModelStandalonePluginCatalog(new DateTime(input.getEffectiveDate()),
+                                                                    ImmutableList.copyOf(input.getCurrentSupportedCurrencies()),
+                                                                    ImmutableList.<Product>copyOf(input.getCurrentProducts()),
+                                                                    ImmutableList.<Plan>copyOf(input.getCurrentPlans()),
+                                                                    input.getStandaloneCatalog().getPriceLists().getDefaultPricelist(),
+                                                                    ImmutableList.<PriceList>copyOf(input.getStandaloneCatalog().getPriceLists().getChildPriceLists()),
+                                                                    input.getStandaloneCatalog().getPlanRules(),
+                                                                    null /*ImmutableList.<Unit>copyOf(input.getStandaloneCatalog().getCurrentUnits()) */);
                     } catch (CatalogApiException e) {
                         throw new IllegalStateException(e);
                     }
                 }
 
-                private <I, C extends I> List<I> listOf(@Nullable C [] input) {
+                private <I, C extends I> List<I> listOf(@Nullable C[] input) {
                     return (input != null) ? ImmutableList.<I>copyOf(input) : ImmutableList.<I>of();
                 }
             });
         }
     }
-
-    private static final class TestVersionedPluginCatalog implements VersionedPluginCatalog {
-
-        private final String catalogName;
-
-        private final BillingMode billingMode;
-
-        private final Iterable<StandalonePluginCatalog> standalonePluginCatalogs;
-
-        public TestVersionedPluginCatalog(final String catalogName,
-                                          final BillingMode billingMode,
-                                          final Iterable<StandalonePluginCatalog> standalonePluginCatalogs) {
-            this.catalogName = catalogName;
-            this.billingMode = billingMode;
-            this.standalonePluginCatalogs = standalonePluginCatalogs;
-        }
-
-        @Override
-        public String getCatalogName() {
-            return catalogName;
-        }
-
-        @Override
-        public BillingMode getRecurringBillingMode() {
-            return billingMode;
-        }
-
-        @Override
-        public Iterable<StandalonePluginCatalog> getStandalonePluginCatalogs() {
-            return standalonePluginCatalogs;
-        }
-    }
-
-    private static class TestStandalonePluginCatalog implements StandalonePluginCatalog {
-
-        private final DateTime effectiveDate;
-
-        private final Iterable<Currency> currency;
-
-        private final Iterable<Product> products;
-
-        private final Iterable<Plan> plans;
-
-        private final PriceList defaultPriceList;
-
-        private final Iterable<PriceList> childrenPriceLists;
-
-        private final PlanRules planRules;
-
-        private final Iterable<Unit> units;
-
-        public TestStandalonePluginCatalog(final DateTime effectiveDate,
-                                           final Iterable<Currency> currency,
-                                           final Iterable<Product> products,
-                                           final Iterable<Plan> plans,
-                                           final PriceList defaultPriceList,
-                                           final Iterable<PriceList> childrenPriceLists,
-                                           final PlanRules planRules,
-                                           final Iterable<Unit> units) {
-            this.effectiveDate = effectiveDate;
-            this.currency = currency;
-            this.products = products;
-            this.plans = plans;
-            this.defaultPriceList = defaultPriceList;
-            this.childrenPriceLists = childrenPriceLists;
-            this.planRules = planRules;
-            this.units = units;
-        }
-
-        @Override
-        public DateTime getEffectiveDate() {
-            return effectiveDate;
-        }
-
-        @Override
-        public Iterable<Currency> getCurrencies() {
-            return currency;
-        }
-
-        @Override
-        public Iterable<Unit> getUnits() {
-            return units;
-        }
-
-        @Override
-        public Iterable<Product> getProducts() {
-            return products;
-        }
-
-        @Override
-        public Iterable<Plan> getPlans() {
-            return plans;
-        }
-
-        @Override
-        public PriceList getDefaultPriceList() {
-            return defaultPriceList;
-        }
-
-        @Override
-        public Iterable<PriceList> getChildrenPriceList() {
-            return childrenPriceLists;
-        }
-
-        @Override
-        public PlanRules getPlanRules() {
-            return planRules;
-        }
-    }
-
-    private static final class TestPlanRules implements PlanRules {
-
-        private final Iterable<Product> products;
-        private final Iterable<Plan> plans;
-        private final Iterable<PriceList> priceLists;
-
-        private final List<CaseChangePlanPolicy> caseChangePlanPolicy;
-        private final List<CaseChangePlanAlignment> caseChangePlanAlignment;
-        private final List<CaseCancelPolicy> caseCancelPolicy;
-        private final List<CaseCreateAlignment> caseCreateAlignment;
-        private final List<CaseBillingAlignment> caseBillingAlignments;
-        private final List<CasePriceList> casePriceList;
-
-        public TestPlanRules(final Iterable<Product> products, Iterable<Plan> plans, Iterable<PriceList> priceLists) {
-            this.products = products;
-            this.plans = plans;
-            this.priceLists = priceLists;
-            this.caseChangePlanPolicy = new ArrayList<CaseChangePlanPolicy>();
-            this.caseChangePlanAlignment = new ArrayList<CaseChangePlanAlignment>();
-            this.caseCancelPolicy = new ArrayList<CaseCancelPolicy>();
-            this.caseCreateAlignment = new ArrayList<CaseCreateAlignment>();
-            this.caseBillingAlignments = new ArrayList<CaseBillingAlignment>();
-            this.casePriceList = new ArrayList<CasePriceList>();
-        }
-
-        public void addCaseBillingAlignmentRule(final CaseBillingAlignment input) {
-            caseBillingAlignments.add(input);
-        }
-
-        public void addCaseBillingAlignmentRule(final Product product,
-                                                final ProductCategory productCategory,
-                                                final BillingPeriod billingPeriod,
-                                                final PriceList priceList,
-                                                final PhaseType phaseType,
-                                                final BillingAlignment billingAlignment) {
-            caseBillingAlignments.add(new TestCaseBillingAlignment(product, productCategory, billingPeriod, priceList, phaseType, billingAlignment));
-        }
-
-        public void addCaseCancelRule(final CaseCancelPolicy input) {
-            caseCancelPolicy.add(input);
-        }
-
-        public void addCaseCancelRule(final Product product,
-                                      final ProductCategory productCategory,
-                                      final BillingPeriod billingPeriod,
-                                      final PriceList priceList,
-                                      final PhaseType phaseType,
-                                      final BillingActionPolicy billingActionPolicy) {
-            caseCancelPolicy.add(new TestCaseCancelPolicy(product, productCategory, billingPeriod, priceList, phaseType, billingActionPolicy));
-
-        }
-
-        public void addCaseChangeAlignmentRule(final CaseChangePlanAlignment input) {
-            caseChangePlanAlignment.add(input);
-        }
-
-        public void addCaseChangeAlignmentRule(final PhaseType phaseType,
-                                               final String fromProduct,
-                                               final ProductCategory fromProductCategory,
-                                               final BillingPeriod fromBillingPeriod,
-                                               final String fromPriceList,
-                                               final String toProduct,
-                                               final ProductCategory toProductCategory,
-                                               final BillingPeriod toBillingPeriod,
-                                               final String toPriceList,
-                                               final PlanAlignmentChange planAlignmentChange) {
-            caseChangePlanAlignment.add(new TestCaseChangePlanAlignment(phaseType, findProduct(fromProduct), fromProductCategory, fromBillingPeriod, findPriceList(fromPriceList), findProduct(toProduct), toProductCategory, toBillingPeriod, findPriceList(toPriceList), planAlignmentChange));
-        }
-
-        public void addCaseChangePlanPolicyRule(final CaseChangePlanPolicy input) {
-            caseChangePlanPolicy.add(input);
-        }
-
-        public void addCaseChangePlanPolicyRule(final PhaseType phaseType,
-                                                final String fromProduct,
-                                                final ProductCategory fromProductCategory,
-                                                final BillingPeriod fromBillingPeriod,
-                                                final String fromPriceList,
-                                                final String toProduct,
-                                                final ProductCategory toProductCategory,
-                                                final BillingPeriod toBillingPeriod,
-                                                final String toPriceList,
-                                                final BillingActionPolicy policy) {
-            caseChangePlanPolicy.add(new TestCaseChangePlanPolicy(phaseType, findProduct(fromProduct), fromProductCategory, fromBillingPeriod, findPriceList(fromPriceList), findProduct(toProduct), toProductCategory, toBillingPeriod, findPriceList(toPriceList), policy));
-        }
-
-        public void addCaseCreateAlignmentRule(final CaseCreateAlignment input) {
-            caseCreateAlignment.add(input);
-        }
-
-        public void addCaseCreateAlignmentRule(final Product product,
-                                               final ProductCategory productCategory,
-                                               final BillingPeriod billingPeriod,
-                                               final PriceList priceList,
-                                               final PlanAlignmentCreate planAlignmentCreate) {
-            caseCreateAlignment.add(new TestCaseCreateAlignment(product, productCategory, billingPeriod, priceList, planAlignmentCreate));
-        }
-
-        public void addPriceListRule(final CasePriceList input) {
-            casePriceList.add(input);
-        }
-
-        public void addPriceListRule(final Product product,
-                                     final ProductCategory productCategory,
-                                     final BillingPeriod billingPeriod,
-                                     final PriceList priceList,
-                                     final PriceList destPriceList) {
-            casePriceList.add(new TestCasePriceList(product, productCategory, billingPeriod, priceList, destPriceList));
-        }
-
-        @Override
-        public Iterable<CaseChangePlanPolicy> getCaseChangePlanPolicy() {
-            return caseChangePlanPolicy;
-        }
-
-        @Override
-        public Iterable<CaseChangePlanAlignment> getCaseChangePlanAlignment() {
-            return caseChangePlanAlignment;
-        }
-
-        @Override
-        public Iterable<CaseCancelPolicy> getCaseCancelPolicy() {
-            return caseCancelPolicy;
-        }
-
-        @Override
-        public Iterable<CaseCreateAlignment> getCaseCreateAlignment() {
-            return caseCreateAlignment;
-        }
-
-        @Override
-        public Iterable<CaseBillingAlignment> getCaseBillingAlignment() {
-            return caseBillingAlignments;
-        }
-
-        @Override
-        public Iterable<CasePriceList> getCasePriceList() {
-            return casePriceList;
-        }
-
-        private Product findProduct(@Nullable final String productName) {
-            return find(products, productName, "products", new Predicate<Product>() {
-                @Override
-                public boolean apply(final Product input) {
-                    return input.getName().equals(productName);
-                }
-            });
-        }
-
-        private Plan findPlan(@Nullable final String planName) {
-            return find(plans, planName, "plans", new Predicate<Plan>() {
-                @Override
-                public boolean apply(final Plan input) {
-                    return input.getName().equals(planName);
-                }
-            });
-        }
-
-        private PriceList findPriceList(@Nullable final String priceListName) {
-            return find(priceLists, priceListName, "pricelists", new Predicate<PriceList>() {
-                @Override
-                public boolean apply(final PriceList input) {
-                    return input.getName().equals(priceListName);
-                }
-            });
-        }
-
-        private <T> T find(final Iterable<T> all, @Nullable final String name, final String what, final Predicate<T> predicate) {
-            if (name == null) {
-                return null;
-            }
-            final T result = Iterables.tryFind(all, predicate).orNull();
-            if (result == null) {
-                throw new IllegalStateException(String.format("%s : cannot find entry %s", what, name));
-            }
-            return result;
-        }
-    }
-
-    public static class TestCasePriceList extends TestCase implements CasePriceList {
-
-        private final PriceList destPriceList;
-
-        public TestCasePriceList(final Product product,
-                                 final ProductCategory productCategory,
-                                 final BillingPeriod billingPeriod,
-                                 final PriceList priceList,
-                                 final PriceList destPriceList) {
-            super(product, productCategory, billingPeriod, priceList);
-            this.destPriceList = destPriceList;
-        }
-
-        @Override
-        public PriceList getDestinationPriceList() {
-            return destPriceList;
-        }
-    }
-
-    public static class TestCaseCreateAlignment extends TestCase implements CaseCreateAlignment {
-
-        private final PlanAlignmentCreate planAlignmentCreate;
-
-        public TestCaseCreateAlignment(final Product product,
-                                       final ProductCategory productCategory,
-                                       final BillingPeriod billingPeriod,
-                                       final PriceList priceList,
-                                       final PlanAlignmentCreate planAlignmentCreate) {
-            super(product, productCategory, billingPeriod, priceList);
-            this.planAlignmentCreate = planAlignmentCreate;
-        }
-
-        @Override
-        public PlanAlignmentCreate getPlanAlignmentCreate() {
-            return planAlignmentCreate;
-        }
-    }
-
-    public static class TestCaseCancelPolicy extends TestCasePhase implements CaseCancelPolicy {
-
-        private final BillingActionPolicy billingActionPolicy;
-
-        public TestCaseCancelPolicy(final Product product,
-                                    final ProductCategory productCategory,
-                                    final BillingPeriod billingPeriod,
-                                    final PriceList priceList,
-                                    final PhaseType phaseType,
-                                    final BillingActionPolicy billingActionPolicy) {
-            super(product, productCategory, billingPeriod, priceList, phaseType);
-            this.billingActionPolicy = billingActionPolicy;
-        }
-
-        @Override
-        public BillingActionPolicy getBillingActionPolicy() {
-            return billingActionPolicy;
-        }
-    }
-
-    public static class TestCaseBillingAlignment extends TestCasePhase implements CaseBillingAlignment {
-
-        private final BillingAlignment billingAlignment;
-
-        public TestCaseBillingAlignment(final Product product,
-                                        final ProductCategory productCategory,
-                                        final BillingPeriod billingPeriod,
-                                        final PriceList priceList,
-                                        final PhaseType phaseType,
-                                        final BillingAlignment billingAlignment) {
-            super(product, productCategory, billingPeriod, priceList, phaseType);
-            this.billingAlignment = billingAlignment;
-        }
-
-        @Override
-        public BillingAlignment getBillingAlignment() {
-            return billingAlignment;
-        }
-    }
-
-    public static class TestCasePhase extends TestCase implements CasePhase {
-
-        private final PhaseType phaseType;
-
-        public TestCasePhase(final Product product,
-                             final ProductCategory productCategory,
-                             final BillingPeriod billingPeriod,
-                             final PriceList priceList,
-                             final PhaseType phaseType) {
-            super(product, productCategory, billingPeriod, priceList);
-            this.phaseType = phaseType;
-        }
-
-        @Override
-        public PhaseType getPhaseType() {
-            return phaseType;
-        }
-    }
-
-    public static class TestCase implements Case {
-
-        private final Product product;
-
-        private final ProductCategory productCategory;
-
-        private final BillingPeriod billingPeriod;
-
-        private final PriceList priceList;
-
-        public TestCase(final Product product,
-                        final ProductCategory productCategory,
-                        final BillingPeriod billingPeriod,
-                        final PriceList priceList) {
-            this.product = product;
-            this.productCategory = productCategory;
-            this.billingPeriod = billingPeriod;
-            this.priceList = priceList;
-        }
-
-        @Override
-        public Product getProduct() {
-            return product;
-        }
-
-        @Override
-        public ProductCategory getProductCategory() {
-            return productCategory;
-        }
-
-        @Override
-        public BillingPeriod getBillingPeriod() {
-            return billingPeriod;
-        }
-
-        @Override
-        public PriceList getPriceList() {
-            return priceList;
-        }
-    }
-
-    public static class TestCaseChangePlanAlignment extends TestCaseChange implements CaseChangePlanAlignment {
-
-        private final PlanAlignmentChange planAlignmentChange;
-
-        public TestCaseChangePlanAlignment(final PhaseType phaseType,
-                                           final Product fromProduct,
-                                           final ProductCategory fromProductCategory,
-                                           final BillingPeriod fromBillingPeriod,
-                                           final PriceList fromPriceList,
-                                           final Product toProduct,
-                                           final ProductCategory toProductCategory,
-                                           final BillingPeriod toBillingPeriod,
-                                           final PriceList toPriceList,
-                                           final PlanAlignmentChange planAlignmentChange) {
-            super(phaseType, fromProduct, fromProductCategory, fromBillingPeriod, fromPriceList, toProduct, toProductCategory, toBillingPeriod, toPriceList);
-            this.planAlignmentChange = planAlignmentChange;
-        }
-
-        @Override
-        public PlanAlignmentChange getAlignment() {
-            return planAlignmentChange;
-        }
-    }
-
-    public static class TestCaseChangePlanPolicy extends TestCaseChange implements CaseChangePlanPolicy {
-
-        private final BillingActionPolicy billingPolicy;
-
-        public TestCaseChangePlanPolicy(final PhaseType phaseType,
-                                        final Product fromProduct,
-                                        final ProductCategory fromProductCategory,
-                                        final BillingPeriod fromBillingPeriod,
-                                        final PriceList fromPriceList,
-                                        final Product toProduct,
-                                        final ProductCategory toProductCategory,
-                                        final BillingPeriod toBillingPeriod,
-                                        final PriceList toPriceList,
-                                        final BillingActionPolicy billingPolicy) {
-            super(phaseType, fromProduct, fromProductCategory, fromBillingPeriod, fromPriceList, toProduct, toProductCategory, toBillingPeriod, toPriceList);
-            this.billingPolicy = billingPolicy;
-        }
-
-        @Override
-        public BillingActionPolicy getBillingActionPolicy() {
-            return billingPolicy;
-        }
-    }
-
-    public static class TestCaseChange implements CaseChange {
-
-        private final PhaseType phaseType;
-
-        private final Product fromProduct;
-
-        private final ProductCategory fromProductCategory;
-
-        private final BillingPeriod fromBillingPeriod;
-
-        private final PriceList fromPriceList;
-
-        private final Product toProduct;
-
-        private final ProductCategory toProductCategory;
-
-        private final BillingPeriod toBillingPeriod;
-
-        private final PriceList toPriceList;
-
-        public TestCaseChange(final PhaseType phaseType,
-                              final Product fromProduct,
-                              final ProductCategory fromProductCategory,
-                              final BillingPeriod fromBillingPeriod,
-                              final PriceList fromPriceList,
-                              final Product toProduct,
-                              final ProductCategory toProductCategory,
-                              final BillingPeriod toBillingPeriod,
-                              final PriceList toPriceList) {
-            this.phaseType = phaseType;
-            this.fromProduct = fromProduct;
-            this.fromProductCategory = fromProductCategory;
-            this.fromBillingPeriod = fromBillingPeriod;
-            this.fromPriceList = fromPriceList;
-            this.toProduct = toProduct;
-            this.toProductCategory = toProductCategory;
-            this.toBillingPeriod = toBillingPeriod;
-            this.toPriceList = toPriceList;
-        }
-
-        @Override
-        public PhaseType getPhaseType() {
-            return phaseType;
-        }
-
-        @Override
-        public Product getFromProduct() {
-            return fromProduct;
-        }
-
-        @Override
-        public ProductCategory getFromProductCategory() {
-            return fromProductCategory;
-        }
-
-        @Override
-        public BillingPeriod getFromBillingPeriod() {
-            return fromBillingPeriod;
-        }
-
-        @Override
-        public PriceList getFromPriceList() {
-            return fromPriceList;
-        }
-
-        @Override
-        public Product getToProduct() {
-            return toProduct;
-        }
-
-        @Override
-        public ProductCategory getToProductCategory() {
-            return toProductCategory;
-        }
-
-        @Override
-        public BillingPeriod getToBillingPeriod() {
-            return toBillingPeriod;
-        }
-
-        @Override
-        public PriceList getToPriceList() {
-            return toPriceList;
-        }
-    }
-
 }
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestCatalogPluginMapping.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestCatalogPluginMapping.java
index 3b724db..ff48895 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestCatalogPluginMapping.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestCatalogPluginMapping.java
@@ -17,44 +17,26 @@
 
 package org.killbill.billing.catalog.plugin;
 
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.annotation.Nullable;
-
 import org.joda.time.DateTime;
 import org.killbill.billing.catalog.CatalogTestSuiteNoDB;
 import org.killbill.billing.catalog.StandaloneCatalog;
-import org.killbill.billing.catalog.api.BillingActionPolicy;
-import org.killbill.billing.catalog.api.BillingAlignment;
-import org.killbill.billing.catalog.api.BillingPeriod;
 import org.killbill.billing.catalog.api.Currency;
-import org.killbill.billing.catalog.api.PhaseType;
 import org.killbill.billing.catalog.api.Plan;
-import org.killbill.billing.catalog.api.PlanAlignmentChange;
-import org.killbill.billing.catalog.api.PlanAlignmentCreate;
 import org.killbill.billing.catalog.api.PriceList;
 import org.killbill.billing.catalog.api.Product;
-import org.killbill.billing.catalog.api.ProductCategory;
 import org.killbill.billing.catalog.api.Unit;
-import org.killbill.billing.catalog.api.rules.Case;
 import org.killbill.billing.catalog.api.rules.CaseBillingAlignment;
 import org.killbill.billing.catalog.api.rules.CaseCancelPolicy;
-import org.killbill.billing.catalog.api.rules.CaseChange;
 import org.killbill.billing.catalog.api.rules.CaseChangePlanAlignment;
 import org.killbill.billing.catalog.api.rules.CaseChangePlanPolicy;
 import org.killbill.billing.catalog.api.rules.CaseCreateAlignment;
-import org.killbill.billing.catalog.api.rules.CasePhase;
 import org.killbill.billing.catalog.api.rules.CasePriceList;
-import org.killbill.billing.catalog.api.rules.PlanRules;
 import org.killbill.billing.catalog.plugin.api.StandalonePluginCatalog;
 import org.killbill.xmlloader.XMLLoader;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
-import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
 import com.google.common.io.Resources;
 
 public class TestCatalogPluginMapping extends CatalogTestSuiteNoDB {
@@ -73,7 +55,7 @@ public class TestCatalogPluginMapping extends CatalogTestSuiteNoDB {
 
     private StandalonePluginCatalog buildStandalonePluginCatalog(final StandaloneCatalog inputCatalog) throws Exception {
 
-        final TestPlanRules rules = new TestPlanRules(ImmutableList.<Product>copyOf(inputCatalog.getCurrentProducts()),
+        final TestModelPlanRules rules = new TestModelPlanRules(ImmutableList.<Product>copyOf(inputCatalog.getCurrentProducts()),
                                                       ImmutableList.<Plan>copyOf(inputCatalog.getCurrentPlans()),
                                                       inputCatalog.getPriceLists().getAllPriceLists());
 
@@ -107,7 +89,7 @@ public class TestCatalogPluginMapping extends CatalogTestSuiteNoDB {
                 rules.addPriceListRule(cur);
             }
         }
-        final TestStandalonePluginCatalog result = new TestStandalonePluginCatalog(new DateTime(inputCatalog.getEffectiveDate()),
+        final TestModelStandalonePluginCatalog result = new TestModelStandalonePluginCatalog(new DateTime(inputCatalog.getEffectiveDate()),
                                                                                    ImmutableList.<Currency>copyOf(inputCatalog.getCurrentSupportedCurrencies()),
                                                                                    ImmutableList.<Product>copyOf(inputCatalog.getCurrentProducts()),
                                                                                    ImmutableList.<Plan>copyOf(inputCatalog.getCurrentPlans()),
@@ -118,531 +100,4 @@ public class TestCatalogPluginMapping extends CatalogTestSuiteNoDB {
         return result;
     }
 
-    private static final class TestPlanRules implements PlanRules {
-
-        private final Iterable<Product> products;
-        private final Iterable<Plan> plans;
-        private final Iterable<PriceList> priceLists;
-
-        private final List<CaseChangePlanPolicy> caseChangePlanPolicy;
-        private final List<CaseChangePlanAlignment> caseChangePlanAlignment;
-        private final List<CaseCancelPolicy> caseCancelPolicy;
-        private final List<CaseCreateAlignment> caseCreateAlignment;
-        private final List<CaseBillingAlignment> caseBillingAlignments;
-        private final List<CasePriceList> casePriceList;
-
-        public TestPlanRules(final Iterable<Product> products, Iterable<Plan> plans, Iterable<PriceList> priceLists) {
-            this.products = products;
-            this.plans = plans;
-            this.priceLists = priceLists;
-            this.caseChangePlanPolicy = new ArrayList<CaseChangePlanPolicy>();
-            this.caseChangePlanAlignment = new ArrayList<CaseChangePlanAlignment>();
-            this.caseCancelPolicy = new ArrayList<CaseCancelPolicy>();
-            this.caseCreateAlignment = new ArrayList<CaseCreateAlignment>();
-            this.caseBillingAlignments = new ArrayList<CaseBillingAlignment>();
-            this.casePriceList = new ArrayList<CasePriceList>();
-        }
-
-        public void addCaseBillingAlignmentRule(final CaseBillingAlignment input) {
-            caseBillingAlignments.add(input);
-        }
-
-        public void addCaseBillingAlignmentRule(final Product product,
-                                                final ProductCategory productCategory,
-                                                final BillingPeriod billingPeriod,
-                                                final PriceList priceList,
-                                                final PhaseType phaseType,
-                                                final BillingAlignment billingAlignment) {
-            caseBillingAlignments.add(new TestCaseBillingAlignment(product, productCategory, billingPeriod, priceList, phaseType, billingAlignment));
-        }
-
-        public void addCaseCancelRule(final CaseCancelPolicy input) {
-            caseCancelPolicy.add(input);
-        }
-
-        public void addCaseCancelRule(final Product product,
-                                      final ProductCategory productCategory,
-                                      final BillingPeriod billingPeriod,
-                                      final PriceList priceList,
-                                      final PhaseType phaseType,
-                                      final BillingActionPolicy billingActionPolicy) {
-            caseCancelPolicy.add(new TestCaseCancelPolicy(product, productCategory, billingPeriod, priceList, phaseType, billingActionPolicy));
-
-        }
-
-        public void addCaseChangeAlignmentRule(final CaseChangePlanAlignment input) {
-            caseChangePlanAlignment.add(input);
-        }
-
-        public void addCaseChangeAlignmentRule(final PhaseType phaseType,
-                                               final String fromProduct,
-                                               final ProductCategory fromProductCategory,
-                                               final BillingPeriod fromBillingPeriod,
-                                               final String fromPriceList,
-                                               final String toProduct,
-                                               final ProductCategory toProductCategory,
-                                               final BillingPeriod toBillingPeriod,
-                                               final String toPriceList,
-                                               final PlanAlignmentChange planAlignmentChange) {
-            caseChangePlanAlignment.add(new TestCaseChangePlanAlignment(phaseType, findProduct(fromProduct), fromProductCategory, fromBillingPeriod, findPriceList(fromPriceList), findProduct(toProduct), toProductCategory, toBillingPeriod, findPriceList(toPriceList), planAlignmentChange));
-        }
-
-        public void addCaseChangePlanPolicyRule(final CaseChangePlanPolicy input) {
-            caseChangePlanPolicy.add(input);
-        }
-
-        public void addCaseChangePlanPolicyRule(final PhaseType phaseType,
-                                                final String fromProduct,
-                                                final ProductCategory fromProductCategory,
-                                                final BillingPeriod fromBillingPeriod,
-                                                final String fromPriceList,
-                                                final String toProduct,
-                                                final ProductCategory toProductCategory,
-                                                final BillingPeriod toBillingPeriod,
-                                                final String toPriceList,
-                                                final BillingActionPolicy policy) {
-            caseChangePlanPolicy.add(new TestCaseChangePlanPolicy(phaseType, findProduct(fromProduct), fromProductCategory, fromBillingPeriod, findPriceList(fromPriceList), findProduct(toProduct), toProductCategory, toBillingPeriod, findPriceList(toPriceList), policy));
-        }
-
-        public void addCaseCreateAlignmentRule(final CaseCreateAlignment input) {
-            caseCreateAlignment.add(input);
-        }
-
-        public void addCaseCreateAlignmentRule(final Product product,
-                                               final ProductCategory productCategory,
-                                               final BillingPeriod billingPeriod,
-                                               final PriceList priceList,
-                                               final PlanAlignmentCreate planAlignmentCreate) {
-            caseCreateAlignment.add(new TestCaseCreateAlignment(product, productCategory, billingPeriod, priceList, planAlignmentCreate));
-        }
-
-        public void addPriceListRule(final CasePriceList input) {
-            casePriceList.add(input);
-        }
-
-        public void addPriceListRule(final Product product,
-                                     final ProductCategory productCategory,
-                                     final BillingPeriod billingPeriod,
-                                     final PriceList priceList,
-                                     final PriceList destPriceList) {
-            casePriceList.add(new TestCasePriceList(product, productCategory, billingPeriod, priceList, destPriceList));
-        }
-
-        @Override
-        public Iterable<CaseChangePlanPolicy> getCaseChangePlanPolicy() {
-            return caseChangePlanPolicy;
-        }
-
-        @Override
-        public Iterable<CaseChangePlanAlignment> getCaseChangePlanAlignment() {
-            return caseChangePlanAlignment;
-        }
-
-        @Override
-        public Iterable<CaseCancelPolicy> getCaseCancelPolicy() {
-            return caseCancelPolicy;
-        }
-
-        @Override
-        public Iterable<CaseCreateAlignment> getCaseCreateAlignment() {
-            return caseCreateAlignment;
-        }
-
-        @Override
-        public Iterable<CaseBillingAlignment> getCaseBillingAlignment() {
-            return caseBillingAlignments;
-        }
-
-        @Override
-        public Iterable<CasePriceList> getCasePriceList() {
-            return casePriceList;
-        }
-
-        private Product findProduct(@Nullable final String productName) {
-            return find(products, productName, "products", new Predicate<Product>() {
-                @Override
-                public boolean apply(final Product input) {
-                    return input.getName().equals(productName);
-                }
-            });
-        }
-
-        private Plan findPlan(@Nullable final String planName) {
-            return find(plans, planName, "plans", new Predicate<Plan>() {
-                @Override
-                public boolean apply(final Plan input) {
-                    return input.getName().equals(planName);
-                }
-            });
-        }
-
-        private PriceList findPriceList(@Nullable final String priceListName) {
-            return find(priceLists, priceListName, "pricelists", new Predicate<PriceList>() {
-                @Override
-                public boolean apply(final PriceList input) {
-                    return input.getName().equals(priceListName);
-                }
-            });
-        }
-
-        private <T> T find(final Iterable<T> all, @Nullable final String name, final String what, final Predicate<T> predicate) {
-            if (name == null) {
-                return null;
-            }
-            final T result = Iterables.tryFind(all, predicate).orNull();
-            if (result == null) {
-                throw new IllegalStateException(String.format("%s : cannot find entry %s", what, name));
-            }
-            return result;
-        }
-    }
-
-    public static class TestCasePriceList extends TestCase implements CasePriceList {
-
-        private final PriceList destPriceList;
-
-        public TestCasePriceList(final Product product,
-                                 final ProductCategory productCategory,
-                                 final BillingPeriod billingPeriod,
-                                 final PriceList priceList,
-                                 final PriceList destPriceList) {
-            super(product, productCategory, billingPeriod, priceList);
-            this.destPriceList = destPriceList;
-        }
-
-        @Override
-        public PriceList getDestinationPriceList() {
-            return destPriceList;
-        }
-    }
-
-    public static class TestCaseCreateAlignment extends TestCase implements CaseCreateAlignment {
-
-        private final PlanAlignmentCreate planAlignmentCreate;
-
-        public TestCaseCreateAlignment(final Product product,
-                                       final ProductCategory productCategory,
-                                       final BillingPeriod billingPeriod,
-                                       final PriceList priceList,
-                                       final PlanAlignmentCreate planAlignmentCreate) {
-            super(product, productCategory, billingPeriod, priceList);
-            this.planAlignmentCreate = planAlignmentCreate;
-        }
-
-        @Override
-        public PlanAlignmentCreate getPlanAlignmentCreate() {
-            return planAlignmentCreate;
-        }
-    }
-
-    public static class TestCaseCancelPolicy extends TestCasePhase implements CaseCancelPolicy {
-
-        private final BillingActionPolicy billingActionPolicy;
-
-        public TestCaseCancelPolicy(final Product product,
-                                    final ProductCategory productCategory,
-                                    final BillingPeriod billingPeriod,
-                                    final PriceList priceList,
-                                    final PhaseType phaseType,
-                                    final BillingActionPolicy billingActionPolicy) {
-            super(product, productCategory, billingPeriod, priceList, phaseType);
-            this.billingActionPolicy = billingActionPolicy;
-        }
-
-        @Override
-        public BillingActionPolicy getBillingActionPolicy() {
-            return billingActionPolicy;
-        }
-    }
-
-    public static class TestCaseBillingAlignment extends TestCasePhase implements CaseBillingAlignment {
-
-        private final BillingAlignment billingAlignment;
-
-        public TestCaseBillingAlignment(final Product product,
-                                        final ProductCategory productCategory,
-                                        final BillingPeriod billingPeriod,
-                                        final PriceList priceList,
-                                        final PhaseType phaseType,
-                                        final BillingAlignment billingAlignment) {
-            super(product, productCategory, billingPeriod, priceList, phaseType);
-            this.billingAlignment = billingAlignment;
-        }
-
-        @Override
-        public BillingAlignment getBillingAlignment() {
-            return billingAlignment;
-        }
-    }
-
-    public static class TestCasePhase extends TestCase implements CasePhase {
-
-        private final PhaseType phaseType;
-
-        public TestCasePhase(final Product product,
-                             final ProductCategory productCategory,
-                             final BillingPeriod billingPeriod,
-                             final PriceList priceList,
-                             final PhaseType phaseType) {
-            super(product, productCategory, billingPeriod, priceList);
-            this.phaseType = phaseType;
-        }
-
-        @Override
-        public PhaseType getPhaseType() {
-            return phaseType;
-        }
-    }
-
-    public static class TestCase implements Case {
-
-        private final Product product;
-
-        private final ProductCategory productCategory;
-
-        private final BillingPeriod billingPeriod;
-
-        private final PriceList priceList;
-
-        public TestCase(final Product product,
-                        final ProductCategory productCategory,
-                        final BillingPeriod billingPeriod,
-                        final PriceList priceList) {
-            this.product = product;
-            this.productCategory = productCategory;
-            this.billingPeriod = billingPeriod;
-            this.priceList = priceList;
-        }
-
-        @Override
-        public Product getProduct() {
-            return product;
-        }
-
-        @Override
-        public ProductCategory getProductCategory() {
-            return productCategory;
-        }
-
-        @Override
-        public BillingPeriod getBillingPeriod() {
-            return billingPeriod;
-        }
-
-        @Override
-        public PriceList getPriceList() {
-            return priceList;
-        }
-    }
-
-    public static class TestCaseChangePlanAlignment extends TestCaseChange implements CaseChangePlanAlignment {
-
-        private final PlanAlignmentChange planAlignmentChange;
-
-        public TestCaseChangePlanAlignment(final PhaseType phaseType,
-                                           final Product fromProduct,
-                                           final ProductCategory fromProductCategory,
-                                           final BillingPeriod fromBillingPeriod,
-                                           final PriceList fromPriceList,
-                                           final Product toProduct,
-                                           final ProductCategory toProductCategory,
-                                           final BillingPeriod toBillingPeriod,
-                                           final PriceList toPriceList,
-                                           final PlanAlignmentChange planAlignmentChange) {
-            super(phaseType, fromProduct, fromProductCategory, fromBillingPeriod, fromPriceList, toProduct, toProductCategory, toBillingPeriod, toPriceList);
-            this.planAlignmentChange = planAlignmentChange;
-        }
-
-        @Override
-        public PlanAlignmentChange getAlignment() {
-            return planAlignmentChange;
-        }
-    }
-
-    public static class TestCaseChangePlanPolicy extends TestCaseChange implements CaseChangePlanPolicy {
-
-        private final BillingActionPolicy billingPolicy;
-
-        public TestCaseChangePlanPolicy(final PhaseType phaseType,
-                                        final Product fromProduct,
-                                        final ProductCategory fromProductCategory,
-                                        final BillingPeriod fromBillingPeriod,
-                                        final PriceList fromPriceList,
-                                        final Product toProduct,
-                                        final ProductCategory toProductCategory,
-                                        final BillingPeriod toBillingPeriod,
-                                        final PriceList toPriceList,
-                                        final BillingActionPolicy billingPolicy) {
-            super(phaseType, fromProduct, fromProductCategory, fromBillingPeriod, fromPriceList, toProduct, toProductCategory, toBillingPeriod, toPriceList);
-            this.billingPolicy = billingPolicy;
-        }
-
-        @Override
-        public BillingActionPolicy getBillingActionPolicy() {
-            return billingPolicy;
-        }
-    }
-
-    public static class TestCaseChange implements CaseChange {
-
-        private final PhaseType phaseType;
-
-        private final Product fromProduct;
-
-        private final ProductCategory fromProductCategory;
-
-        private final BillingPeriod fromBillingPeriod;
-
-        private final PriceList fromPriceList;
-
-        private final Product toProduct;
-
-        private final ProductCategory toProductCategory;
-
-        private final BillingPeriod toBillingPeriod;
-
-        private final PriceList toPriceList;
-
-        public TestCaseChange(final PhaseType phaseType,
-                              final Product fromProduct,
-                              final ProductCategory fromProductCategory,
-                              final BillingPeriod fromBillingPeriod,
-                              final PriceList fromPriceList,
-                              final Product toProduct,
-                              final ProductCategory toProductCategory,
-                              final BillingPeriod toBillingPeriod,
-                              final PriceList toPriceList) {
-            this.phaseType = phaseType;
-            this.fromProduct = fromProduct;
-            this.fromProductCategory = fromProductCategory;
-            this.fromBillingPeriod = fromBillingPeriod;
-            this.fromPriceList = fromPriceList;
-            this.toProduct = toProduct;
-            this.toProductCategory = toProductCategory;
-            this.toBillingPeriod = toBillingPeriod;
-            this.toPriceList = toPriceList;
-        }
-
-        @Override
-        public PhaseType getPhaseType() {
-            return phaseType;
-        }
-
-        @Override
-        public Product getFromProduct() {
-            return fromProduct;
-        }
-
-        @Override
-        public ProductCategory getFromProductCategory() {
-            return fromProductCategory;
-        }
-
-        @Override
-        public BillingPeriod getFromBillingPeriod() {
-            return fromBillingPeriod;
-        }
-
-        @Override
-        public PriceList getFromPriceList() {
-            return fromPriceList;
-        }
-
-        @Override
-        public Product getToProduct() {
-            return toProduct;
-        }
-
-        @Override
-        public ProductCategory getToProductCategory() {
-            return toProductCategory;
-        }
-
-        @Override
-        public BillingPeriod getToBillingPeriod() {
-            return toBillingPeriod;
-        }
-
-        @Override
-        public PriceList getToPriceList() {
-            return toPriceList;
-        }
-    }
-
-    private static class TestStandalonePluginCatalog implements StandalonePluginCatalog {
-
-        private final DateTime effectiveDate;
-
-        private final Iterable<Currency> currency;
-
-        private final Iterable<Product> products;
-
-        private final Iterable<Plan> plans;
-
-        private final PriceList defaultPriceList;
-
-        private final Iterable<PriceList> childrenPriceLists;
-
-        private final PlanRules planRules;
-
-        private final Iterable<Unit> units;
-
-        public TestStandalonePluginCatalog(final DateTime effectiveDate,
-                                           final Iterable<Currency> currency,
-                                           final Iterable<Product> products,
-                                           final Iterable<Plan> plans,
-                                           final PriceList defaultPriceList,
-                                           final Iterable<PriceList> childrenPriceLists,
-                                           final PlanRules planRules,
-                                           final Iterable<Unit> units) {
-            this.effectiveDate = effectiveDate;
-            this.currency = currency;
-            this.products = products;
-            this.plans = plans;
-            this.defaultPriceList = defaultPriceList;
-            this.childrenPriceLists = childrenPriceLists;
-            this.planRules = planRules;
-            this.units = units;
-        }
-
-        @Override
-        public DateTime getEffectiveDate() {
-            return effectiveDate;
-        }
-
-        @Override
-        public Iterable<Currency> getCurrencies() {
-            return currency;
-        }
-
-        @Override
-        public Iterable<Unit> getUnits() {
-            return units;
-        }
-
-        @Override
-        public Iterable<Product> getProducts() {
-            return products;
-        }
-
-        @Override
-        public Iterable<Plan> getPlans() {
-            return plans;
-        }
-
-        @Override
-        public PriceList getDefaultPriceList() {
-            return defaultPriceList;
-        }
-
-        @Override
-        public Iterable<PriceList> getChildrenPriceList() {
-            return childrenPriceLists;
-        }
-
-        @Override
-        public PlanRules getPlanRules() {
-            return planRules;
-        }
-    }
 }
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCase.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCase.java
new file mode 100644
index 0000000..b702309
--- /dev/null
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCase.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.catalog.plugin;
+
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.PriceList;
+import org.killbill.billing.catalog.api.Product;
+import org.killbill.billing.catalog.api.ProductCategory;
+import org.killbill.billing.catalog.api.rules.Case;
+
+public class TestModelCase implements Case {
+
+    private final Product product;
+
+    private final ProductCategory productCategory;
+
+    private final BillingPeriod billingPeriod;
+
+    private final PriceList priceList;
+
+    public TestModelCase(final Product product,
+                         final ProductCategory productCategory,
+                         final BillingPeriod billingPeriod,
+                         final PriceList priceList) {
+        this.product = product;
+        this.productCategory = productCategory;
+        this.billingPeriod = billingPeriod;
+        this.priceList = priceList;
+    }
+
+    @Override
+    public Product getProduct() {
+        return product;
+    }
+
+    @Override
+    public ProductCategory getProductCategory() {
+        return productCategory;
+    }
+
+    @Override
+    public BillingPeriod getBillingPeriod() {
+        return billingPeriod;
+    }
+
+    @Override
+    public PriceList getPriceList() {
+        return priceList;
+    }
+}
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseBillingAlignment.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseBillingAlignment.java
new file mode 100644
index 0000000..1757fef
--- /dev/null
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseBillingAlignment.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.catalog.plugin;
+
+import org.killbill.billing.catalog.api.BillingAlignment;
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.PhaseType;
+import org.killbill.billing.catalog.api.PriceList;
+import org.killbill.billing.catalog.api.Product;
+import org.killbill.billing.catalog.api.ProductCategory;
+import org.killbill.billing.catalog.api.rules.CaseBillingAlignment;
+
+public class TestModelCaseBillingAlignment extends TestModelCasePhase implements CaseBillingAlignment {
+
+    private final BillingAlignment billingAlignment;
+
+    public TestModelCaseBillingAlignment(final Product product,
+                                         final ProductCategory productCategory,
+                                         final BillingPeriod billingPeriod,
+                                         final PriceList priceList,
+                                         final PhaseType phaseType,
+                                         final BillingAlignment billingAlignment) {
+        super(product, productCategory, billingPeriod, priceList, phaseType);
+        this.billingAlignment = billingAlignment;
+    }
+
+    @Override
+    public BillingAlignment getBillingAlignment() {
+        return billingAlignment;
+    }
+}
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseCancelPolicy.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseCancelPolicy.java
new file mode 100644
index 0000000..7a64e40
--- /dev/null
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseCancelPolicy.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.catalog.plugin;
+
+import org.killbill.billing.catalog.api.BillingActionPolicy;
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.PhaseType;
+import org.killbill.billing.catalog.api.PriceList;
+import org.killbill.billing.catalog.api.Product;
+import org.killbill.billing.catalog.api.ProductCategory;
+import org.killbill.billing.catalog.api.rules.CaseCancelPolicy;
+
+public class TestModelCaseCancelPolicy extends TestModelCasePhase implements CaseCancelPolicy {
+
+    private final BillingActionPolicy billingActionPolicy;
+
+    public TestModelCaseCancelPolicy(final Product product,
+                                     final ProductCategory productCategory,
+                                     final BillingPeriod billingPeriod,
+                                     final PriceList priceList,
+                                     final PhaseType phaseType,
+                                     final BillingActionPolicy billingActionPolicy) {
+        super(product, productCategory, billingPeriod, priceList, phaseType);
+        this.billingActionPolicy = billingActionPolicy;
+    }
+
+    @Override
+    public BillingActionPolicy getBillingActionPolicy() {
+        return billingActionPolicy;
+    }
+}
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseChange.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseChange.java
new file mode 100644
index 0000000..60bd92b
--- /dev/null
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseChange.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.catalog.plugin;
+
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.PhaseType;
+import org.killbill.billing.catalog.api.PriceList;
+import org.killbill.billing.catalog.api.Product;
+import org.killbill.billing.catalog.api.ProductCategory;
+import org.killbill.billing.catalog.api.rules.CaseChange;
+
+public class TestModelCaseChange implements CaseChange {
+
+    private final PhaseType phaseType;
+
+    private final Product fromProduct;
+
+    private final ProductCategory fromProductCategory;
+
+    private final BillingPeriod fromBillingPeriod;
+
+    private final PriceList fromPriceList;
+
+    private final Product toProduct;
+
+    private final ProductCategory toProductCategory;
+
+    private final BillingPeriod toBillingPeriod;
+
+    private final PriceList toPriceList;
+
+    public TestModelCaseChange(final PhaseType phaseType,
+                               final Product fromProduct,
+                               final ProductCategory fromProductCategory,
+                               final BillingPeriod fromBillingPeriod,
+                               final PriceList fromPriceList,
+                               final Product toProduct,
+                               final ProductCategory toProductCategory,
+                               final BillingPeriod toBillingPeriod,
+                               final PriceList toPriceList) {
+        this.phaseType = phaseType;
+        this.fromProduct = fromProduct;
+        this.fromProductCategory = fromProductCategory;
+        this.fromBillingPeriod = fromBillingPeriod;
+        this.fromPriceList = fromPriceList;
+        this.toProduct = toProduct;
+        this.toProductCategory = toProductCategory;
+        this.toBillingPeriod = toBillingPeriod;
+        this.toPriceList = toPriceList;
+    }
+
+    @Override
+    public PhaseType getPhaseType() {
+        return phaseType;
+    }
+
+    @Override
+    public Product getFromProduct() {
+        return fromProduct;
+    }
+
+    @Override
+    public ProductCategory getFromProductCategory() {
+        return fromProductCategory;
+    }
+
+    @Override
+    public BillingPeriod getFromBillingPeriod() {
+        return fromBillingPeriod;
+    }
+
+    @Override
+    public PriceList getFromPriceList() {
+        return fromPriceList;
+    }
+
+    @Override
+    public Product getToProduct() {
+        return toProduct;
+    }
+
+    @Override
+    public ProductCategory getToProductCategory() {
+        return toProductCategory;
+    }
+
+    @Override
+    public BillingPeriod getToBillingPeriod() {
+        return toBillingPeriod;
+    }
+
+    @Override
+    public PriceList getToPriceList() {
+        return toPriceList;
+    }
+}
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseChangePlanAlignment.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseChangePlanAlignment.java
new file mode 100644
index 0000000..e7465a7
--- /dev/null
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseChangePlanAlignment.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.catalog.plugin;
+
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.PhaseType;
+import org.killbill.billing.catalog.api.PlanAlignmentChange;
+import org.killbill.billing.catalog.api.PriceList;
+import org.killbill.billing.catalog.api.Product;
+import org.killbill.billing.catalog.api.ProductCategory;
+import org.killbill.billing.catalog.api.rules.CaseChangePlanAlignment;
+
+public class TestModelCaseChangePlanAlignment extends TestModelCaseChange implements CaseChangePlanAlignment {
+
+    private final PlanAlignmentChange planAlignmentChange;
+
+    public TestModelCaseChangePlanAlignment(final PhaseType phaseType,
+                                            final Product fromProduct,
+                                            final ProductCategory fromProductCategory,
+                                            final BillingPeriod fromBillingPeriod,
+                                            final PriceList fromPriceList,
+                                            final Product toProduct,
+                                            final ProductCategory toProductCategory,
+                                            final BillingPeriod toBillingPeriod,
+                                            final PriceList toPriceList,
+                                            final PlanAlignmentChange planAlignmentChange) {
+        super(phaseType, fromProduct, fromProductCategory, fromBillingPeriod, fromPriceList, toProduct, toProductCategory, toBillingPeriod, toPriceList);
+        this.planAlignmentChange = planAlignmentChange;
+    }
+
+    @Override
+    public PlanAlignmentChange getAlignment() {
+        return planAlignmentChange;
+    }
+}
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseChangePlanPolicy.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseChangePlanPolicy.java
new file mode 100644
index 0000000..8e80227
--- /dev/null
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseChangePlanPolicy.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.catalog.plugin;
+
+import org.killbill.billing.catalog.api.BillingActionPolicy;
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.PhaseType;
+import org.killbill.billing.catalog.api.PriceList;
+import org.killbill.billing.catalog.api.Product;
+import org.killbill.billing.catalog.api.ProductCategory;
+import org.killbill.billing.catalog.api.rules.CaseChangePlanPolicy;
+
+public class TestModelCaseChangePlanPolicy extends TestModelCaseChange implements CaseChangePlanPolicy {
+
+    private final BillingActionPolicy billingPolicy;
+
+    public TestModelCaseChangePlanPolicy(final PhaseType phaseType,
+                                         final Product fromProduct,
+                                         final ProductCategory fromProductCategory,
+                                         final BillingPeriod fromBillingPeriod,
+                                         final PriceList fromPriceList,
+                                         final Product toProduct,
+                                         final ProductCategory toProductCategory,
+                                         final BillingPeriod toBillingPeriod,
+                                         final PriceList toPriceList,
+                                         final BillingActionPolicy billingPolicy) {
+        super(phaseType, fromProduct, fromProductCategory, fromBillingPeriod, fromPriceList, toProduct, toProductCategory, toBillingPeriod, toPriceList);
+        this.billingPolicy = billingPolicy;
+    }
+
+    @Override
+    public BillingActionPolicy getBillingActionPolicy() {
+        return billingPolicy;
+    }
+}
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseCreateAlignment.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseCreateAlignment.java
new file mode 100644
index 0000000..8feaf9b
--- /dev/null
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCaseCreateAlignment.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.catalog.plugin;
+
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.PlanAlignmentCreate;
+import org.killbill.billing.catalog.api.PriceList;
+import org.killbill.billing.catalog.api.Product;
+import org.killbill.billing.catalog.api.ProductCategory;
+import org.killbill.billing.catalog.api.rules.CaseCreateAlignment;
+
+public class TestModelCaseCreateAlignment extends TestModelCase implements CaseCreateAlignment {
+
+    private final PlanAlignmentCreate planAlignmentCreate;
+
+    public TestModelCaseCreateAlignment(final Product product,
+                                        final ProductCategory productCategory,
+                                        final BillingPeriod billingPeriod,
+                                        final PriceList priceList,
+                                        final PlanAlignmentCreate planAlignmentCreate) {
+        super(product, productCategory, billingPeriod, priceList);
+        this.planAlignmentCreate = planAlignmentCreate;
+    }
+
+    @Override
+    public PlanAlignmentCreate getPlanAlignmentCreate() {
+        return planAlignmentCreate;
+    }
+}
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCasePhase.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCasePhase.java
new file mode 100644
index 0000000..760b7fd
--- /dev/null
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCasePhase.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.catalog.plugin;
+
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.PhaseType;
+import org.killbill.billing.catalog.api.PriceList;
+import org.killbill.billing.catalog.api.Product;
+import org.killbill.billing.catalog.api.ProductCategory;
+import org.killbill.billing.catalog.api.rules.CasePhase;
+
+public class TestModelCasePhase extends TestModelCase implements CasePhase {
+
+    private final PhaseType phaseType;
+
+    public TestModelCasePhase(final Product product,
+                              final ProductCategory productCategory,
+                              final BillingPeriod billingPeriod,
+                              final PriceList priceList,
+                              final PhaseType phaseType) {
+        super(product, productCategory, billingPeriod, priceList);
+        this.phaseType = phaseType;
+    }
+
+    @Override
+    public PhaseType getPhaseType() {
+        return phaseType;
+    }
+}
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCasePriceList.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCasePriceList.java
new file mode 100644
index 0000000..258cb7b
--- /dev/null
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelCasePriceList.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.catalog.plugin;
+
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.PriceList;
+import org.killbill.billing.catalog.api.Product;
+import org.killbill.billing.catalog.api.ProductCategory;
+import org.killbill.billing.catalog.api.rules.CasePriceList;
+
+public class TestModelCasePriceList extends TestModelCase implements CasePriceList {
+
+    private final PriceList destPriceList;
+
+    public TestModelCasePriceList(final Product product,
+                                  final ProductCategory productCategory,
+                                  final BillingPeriod billingPeriod,
+                                  final PriceList priceList,
+                                  final PriceList destPriceList) {
+        super(product, productCategory, billingPeriod, priceList);
+        this.destPriceList = destPriceList;
+    }
+
+    @Override
+    public PriceList getDestinationPriceList() {
+        return destPriceList;
+    }
+}
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelPlanRules.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelPlanRules.java
new file mode 100644
index 0000000..97345d2
--- /dev/null
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelPlanRules.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.catalog.plugin;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import org.killbill.billing.catalog.api.BillingActionPolicy;
+import org.killbill.billing.catalog.api.BillingAlignment;
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.PhaseType;
+import org.killbill.billing.catalog.api.Plan;
+import org.killbill.billing.catalog.api.PlanAlignmentChange;
+import org.killbill.billing.catalog.api.PlanAlignmentCreate;
+import org.killbill.billing.catalog.api.PriceList;
+import org.killbill.billing.catalog.api.Product;
+import org.killbill.billing.catalog.api.ProductCategory;
+import org.killbill.billing.catalog.api.rules.CaseBillingAlignment;
+import org.killbill.billing.catalog.api.rules.CaseCancelPolicy;
+import org.killbill.billing.catalog.api.rules.CaseChangePlanAlignment;
+import org.killbill.billing.catalog.api.rules.CaseChangePlanPolicy;
+import org.killbill.billing.catalog.api.rules.CaseCreateAlignment;
+import org.killbill.billing.catalog.api.rules.CasePriceList;
+import org.killbill.billing.catalog.api.rules.PlanRules;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+
+public class TestModelPlanRules implements PlanRules {
+
+    private final Iterable<Product> products;
+    private final Iterable<Plan> plans;
+    private final Iterable<PriceList> priceLists;
+
+    private final List<CaseChangePlanPolicy> caseChangePlanPolicy;
+    private final List<CaseChangePlanAlignment> caseChangePlanAlignment;
+    private final List<CaseCancelPolicy> caseCancelPolicy;
+    private final List<CaseCreateAlignment> caseCreateAlignment;
+    private final List<CaseBillingAlignment> caseBillingAlignments;
+    private final List<CasePriceList> casePriceList;
+
+    public TestModelPlanRules(final Iterable<Product> products, Iterable<Plan> plans, Iterable<PriceList> priceLists) {
+        this.products = products;
+        this.plans = plans;
+        this.priceLists = priceLists;
+        this.caseChangePlanPolicy = new ArrayList<CaseChangePlanPolicy>();
+        this.caseChangePlanAlignment = new ArrayList<CaseChangePlanAlignment>();
+        this.caseCancelPolicy = new ArrayList<CaseCancelPolicy>();
+        this.caseCreateAlignment = new ArrayList<CaseCreateAlignment>();
+        this.caseBillingAlignments = new ArrayList<CaseBillingAlignment>();
+        this.casePriceList = new ArrayList<CasePriceList>();
+    }
+
+    public void addCaseBillingAlignmentRule(final CaseBillingAlignment input) {
+        caseBillingAlignments.add(input);
+    }
+
+    public void addCaseBillingAlignmentRule(final Product product,
+                                            final ProductCategory productCategory,
+                                            final BillingPeriod billingPeriod,
+                                            final PriceList priceList,
+                                            final PhaseType phaseType,
+                                            final BillingAlignment billingAlignment) {
+        caseBillingAlignments.add(new TestModelCaseBillingAlignment(product, productCategory, billingPeriod, priceList, phaseType, billingAlignment));
+    }
+
+    public void addCaseCancelRule(final CaseCancelPolicy input) {
+        caseCancelPolicy.add(input);
+    }
+
+    public void addCaseCancelRule(final Product product,
+                                  final ProductCategory productCategory,
+                                  final BillingPeriod billingPeriod,
+                                  final PriceList priceList,
+                                  final PhaseType phaseType,
+                                  final BillingActionPolicy billingActionPolicy) {
+        caseCancelPolicy.add(new TestModelCaseCancelPolicy(product, productCategory, billingPeriod, priceList, phaseType, billingActionPolicy));
+
+    }
+
+    public void addCaseChangeAlignmentRule(final CaseChangePlanAlignment input) {
+        caseChangePlanAlignment.add(input);
+    }
+
+    public void addCaseChangeAlignmentRule(final PhaseType phaseType,
+                                           final String fromProduct,
+                                           final ProductCategory fromProductCategory,
+                                           final BillingPeriod fromBillingPeriod,
+                                           final String fromPriceList,
+                                           final String toProduct,
+                                           final ProductCategory toProductCategory,
+                                           final BillingPeriod toBillingPeriod,
+                                           final String toPriceList,
+                                           final PlanAlignmentChange planAlignmentChange) {
+        caseChangePlanAlignment.add(new TestModelCaseChangePlanAlignment(phaseType, findProduct(fromProduct), fromProductCategory, fromBillingPeriod, findPriceList(fromPriceList), findProduct(toProduct), toProductCategory, toBillingPeriod, findPriceList(toPriceList), planAlignmentChange));
+    }
+
+    public void addCaseChangePlanPolicyRule(final CaseChangePlanPolicy input) {
+        caseChangePlanPolicy.add(input);
+    }
+
+    public void addCaseChangePlanPolicyRule(final PhaseType phaseType,
+                                            final String fromProduct,
+                                            final ProductCategory fromProductCategory,
+                                            final BillingPeriod fromBillingPeriod,
+                                            final String fromPriceList,
+                                            final String toProduct,
+                                            final ProductCategory toProductCategory,
+                                            final BillingPeriod toBillingPeriod,
+                                            final String toPriceList,
+                                            final BillingActionPolicy policy) {
+        caseChangePlanPolicy.add(new TestModelCaseChangePlanPolicy(phaseType, findProduct(fromProduct), fromProductCategory, fromBillingPeriod, findPriceList(fromPriceList), findProduct(toProduct), toProductCategory, toBillingPeriod, findPriceList(toPriceList), policy));
+    }
+
+    public void addCaseCreateAlignmentRule(final CaseCreateAlignment input) {
+        caseCreateAlignment.add(input);
+    }
+
+    public void addCaseCreateAlignmentRule(final Product product,
+                                           final ProductCategory productCategory,
+                                           final BillingPeriod billingPeriod,
+                                           final PriceList priceList,
+                                           final PlanAlignmentCreate planAlignmentCreate) {
+        caseCreateAlignment.add(new TestModelCaseCreateAlignment(product, productCategory, billingPeriod, priceList, planAlignmentCreate));
+    }
+
+    public void addPriceListRule(final CasePriceList input) {
+        casePriceList.add(input);
+    }
+
+    public void addPriceListRule(final Product product,
+                                 final ProductCategory productCategory,
+                                 final BillingPeriod billingPeriod,
+                                 final PriceList priceList,
+                                 final PriceList destPriceList) {
+        casePriceList.add(new TestModelCasePriceList(product, productCategory, billingPeriod, priceList, destPriceList));
+    }
+
+    @Override
+    public Iterable<CaseChangePlanPolicy> getCaseChangePlanPolicy() {
+        return caseChangePlanPolicy;
+    }
+
+    @Override
+    public Iterable<CaseChangePlanAlignment> getCaseChangePlanAlignment() {
+        return caseChangePlanAlignment;
+    }
+
+    @Override
+    public Iterable<CaseCancelPolicy> getCaseCancelPolicy() {
+        return caseCancelPolicy;
+    }
+
+    @Override
+    public Iterable<CaseCreateAlignment> getCaseCreateAlignment() {
+        return caseCreateAlignment;
+    }
+
+    @Override
+    public Iterable<CaseBillingAlignment> getCaseBillingAlignment() {
+        return caseBillingAlignments;
+    }
+
+    @Override
+    public Iterable<CasePriceList> getCasePriceList() {
+        return casePriceList;
+    }
+
+    private Product findProduct(@Nullable final String productName) {
+        return find(products, productName, "products", new Predicate<Product>() {
+            @Override
+            public boolean apply(final Product input) {
+                return input.getName().equals(productName);
+            }
+        });
+    }
+
+    private Plan findPlan(@Nullable final String planName) {
+        return find(plans, planName, "plans", new Predicate<Plan>() {
+            @Override
+            public boolean apply(final Plan input) {
+                return input.getName().equals(planName);
+            }
+        });
+    }
+
+    private PriceList findPriceList(@Nullable final String priceListName) {
+        return find(priceLists, priceListName, "pricelists", new Predicate<PriceList>() {
+            @Override
+            public boolean apply(final PriceList input) {
+                return input.getName().equals(priceListName);
+            }
+        });
+    }
+
+    private <T> T find(final Iterable<T> all, @Nullable final String name, final String what, final Predicate<T> predicate) {
+        if (name == null) {
+            return null;
+        }
+        final T result = Iterables.tryFind(all, predicate).orNull();
+        if (result == null) {
+            throw new IllegalStateException(String.format("%s : cannot find entry %s", what, name));
+        }
+        return result;
+    }
+}
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelStandalonePluginCatalog.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelStandalonePluginCatalog.java
new file mode 100644
index 0000000..f49cfd5
--- /dev/null
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelStandalonePluginCatalog.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.catalog.plugin;
+
+import org.joda.time.DateTime;
+import org.killbill.billing.catalog.api.Currency;
+import org.killbill.billing.catalog.api.Plan;
+import org.killbill.billing.catalog.api.PriceList;
+import org.killbill.billing.catalog.api.Product;
+import org.killbill.billing.catalog.api.Unit;
+import org.killbill.billing.catalog.api.rules.PlanRules;
+import org.killbill.billing.catalog.plugin.api.StandalonePluginCatalog;
+
+public class TestModelStandalonePluginCatalog implements StandalonePluginCatalog {
+
+    private final DateTime effectiveDate;
+
+    private final Iterable<Currency> currency;
+
+    private final Iterable<Product> products;
+
+    private final Iterable<Plan> plans;
+
+    private final PriceList defaultPriceList;
+
+    private final Iterable<PriceList> childrenPriceLists;
+
+    private final PlanRules planRules;
+
+    private final Iterable<Unit> units;
+
+    public TestModelStandalonePluginCatalog(final DateTime effectiveDate,
+                                            final Iterable<Currency> currency,
+                                            final Iterable<Product> products,
+                                            final Iterable<Plan> plans,
+                                            final PriceList defaultPriceList,
+                                            final Iterable<PriceList> childrenPriceLists,
+                                            final PlanRules planRules,
+                                            final Iterable<Unit> units) {
+        this.effectiveDate = effectiveDate;
+        this.currency = currency;
+        this.products = products;
+        this.plans = plans;
+        this.defaultPriceList = defaultPriceList;
+        this.childrenPriceLists = childrenPriceLists;
+        this.planRules = planRules;
+        this.units = units;
+    }
+
+    @Override
+    public DateTime getEffectiveDate() {
+        return effectiveDate;
+    }
+
+    @Override
+    public Iterable<Currency> getCurrencies() {
+        return currency;
+    }
+
+    @Override
+    public Iterable<Unit> getUnits() {
+        return units;
+    }
+
+    @Override
+    public Iterable<Product> getProducts() {
+        return products;
+    }
+
+    @Override
+    public Iterable<Plan> getPlans() {
+        return plans;
+    }
+
+    @Override
+    public PriceList getDefaultPriceList() {
+        return defaultPriceList;
+    }
+
+    @Override
+    public Iterable<PriceList> getChildrenPriceList() {
+        return childrenPriceLists;
+    }
+
+    @Override
+    public PlanRules getPlanRules() {
+        return planRules;
+    }
+}
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelVersionedPluginCatalog.java b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelVersionedPluginCatalog.java
new file mode 100644
index 0000000..18de96f
--- /dev/null
+++ b/catalog/src/test/java/org/killbill/billing/catalog/plugin/TestModelVersionedPluginCatalog.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.catalog.plugin;
+
+import org.killbill.billing.catalog.api.BillingMode;
+import org.killbill.billing.catalog.plugin.api.StandalonePluginCatalog;
+import org.killbill.billing.catalog.plugin.api.VersionedPluginCatalog;
+
+public class TestModelVersionedPluginCatalog implements VersionedPluginCatalog {
+    private final String catalogName;
+
+    private final BillingMode billingMode;
+
+    private final Iterable<StandalonePluginCatalog> standalonePluginCatalogs;
+
+    public TestModelVersionedPluginCatalog(final String catalogName,
+                                      final BillingMode billingMode,
+                                      final Iterable<StandalonePluginCatalog> standalonePluginCatalogs) {
+        this.catalogName = catalogName;
+        this.billingMode = billingMode;
+        this.standalonePluginCatalogs = standalonePluginCatalogs;
+    }
+
+    @Override
+    public String getCatalogName() {
+        return catalogName;
+    }
+
+    @Override
+    public BillingMode getRecurringBillingMode() {
+        return billingMode;
+    }
+
+    @Override
+    public Iterable<StandalonePluginCatalog> getStandalonePluginCatalogs() {
+        return standalonePluginCatalogs;
+    }
+}