killbill-memoizeit

catalog: Initial refactoring for catalog data structure to

9/30/2016 3:28:21 PM

Details

diff --git a/catalog/src/main/java/org/killbill/billing/catalog/CatalogEntityCollection.java b/catalog/src/main/java/org/killbill/billing/catalog/CatalogEntityCollection.java
new file mode 100644
index 0000000..15873b9
--- /dev/null
+++ b/catalog/src/main/java/org/killbill/billing/catalog/CatalogEntityCollection.java
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2014-2016 Groupon, Inc
+ * Copyright 2014-2016 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;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.killbill.billing.catalog.api.CatalogEntity;
+import org.weakref.jmx.internal.guava.collect.Ordering;
+
+public class CatalogEntityCollection<T extends CatalogEntity> implements Collection<T> {
+
+    private final Set<String> keys;
+    private final HashMap<String, T> data;
+
+    public CatalogEntityCollection() {
+        this.keys = new TreeSet<String>(Ordering.<String>natural());
+        this.data = new HashMap<String, T>();
+    }
+
+    public CatalogEntityCollection(final T[] entities) {
+        this.keys = new TreeSet<String>(Ordering.<String>natural());
+        this.data = new HashMap<String, T>();
+        for (final T cur : entities) {
+            addEntry(cur);
+        }
+    }
+
+    //
+    // Returning such entries will be log(N)
+    //
+    public T findByName(final String entryName) {
+        return data.get(entryName);
+    }
+
+    public Collection<T> getEntries() {
+        return data.values();
+    }
+
+    @Override
+    public int size() {
+        return data.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return data.isEmpty();
+    }
+
+    @Override
+    public boolean contains(final Object o) {
+        return data.containsKey(((CatalogEntity) o).getName());
+    }
+
+    @Override
+    public Iterator iterator() {
+        // Build an iterator that will return ordered using natural ordering with regard to CatalogEntity#name
+        final Iterator<String> keyIterator = keys.iterator();
+        final Iterator it = new Iterator() {
+
+            private String prevKey = null;
+
+            @Override
+            public boolean hasNext() {
+                return keyIterator.hasNext();
+            }
+            @Override
+            public Object next() {
+                prevKey = keyIterator.next();
+                return data.get(prevKey);
+            }
+            @Override
+            public void remove() {
+                if (prevKey != null) {
+                    keyIterator.remove();
+                    data.remove(prevKey);
+                }
+            }
+        };
+        return it;
+    }
+
+
+    @Override
+    public boolean add(final T t) {
+        addEntry(t);
+        return true;
+    }
+
+    @Override
+    public boolean remove(final Object o) {
+        return removeEntry((T) o);
+    }
+
+    @Override
+    public boolean addAll(final Collection c) {
+        final Iterator iterator = c.iterator();
+        while (iterator.hasNext()) {
+            final T cur = (T) iterator.next();
+            addEntry(cur);
+        }
+        return true;
+    }
+
+    @Override
+    public void clear() {
+        data.clear();
+    }
+
+    @Override
+    public boolean retainAll(final Collection c) {
+        throw new IllegalStateException("Not implemented");
+    }
+
+    @Override
+    public boolean removeAll(final Collection c) {
+        final Iterator iterator = c.iterator();
+        while (iterator.hasNext()) {
+            final CatalogEntity cur = (CatalogEntity) iterator.next();
+            data.remove(cur.getName());
+        }
+        return true;
+    }
+
+    @Override
+    public boolean containsAll(final Collection c) {
+        final Iterator iterator = c.iterator();
+        while (iterator.hasNext()) {
+            final CatalogEntity cur = (CatalogEntity) iterator.next();
+            if (!data.containsKey(cur.getName())) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public Object[] toArray(final Object[] a) {
+        return data.values().toArray(a);
+    }
+
+    @Override
+    public Object[] toArray() {
+        return data.values().toArray(new Object[data.size()]);
+    }
+
+
+    @Override
+    public boolean equals(final Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof CatalogEntityCollection)) {
+            return false;
+        }
+
+        final CatalogEntityCollection<?> that = (CatalogEntityCollection<?>) o;
+
+        return data != null ? data.equals(that.data) : that.data == null;
+
+    }
+
+    @Override
+    public int hashCode() {
+        return data != null ? data.hashCode() : 0;
+    }
+
+    private void addEntry(final T entry) {
+        keys.add(entry.getName());
+        data.put(entry.getName(), entry);
+    }
+
+    private boolean removeEntry(final T entry) {
+        keys.remove(entry.getName());
+        return data.remove(entry.getName()) != null;
+    }
+
+}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlan.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlan.java
index 856fd91..61eb0ae 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlan.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlan.java
@@ -314,11 +314,10 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
     }
 
     private String findPriceListForPlan(final StandaloneCatalog catalog) {
-        for (PriceList cur : catalog.getPriceLists().getAllPriceLists()) {
-            for (Plan p : cur.getPlans()) {
-                if (p.getName().equals(name)) {
-                    return ((DefaultPriceList) cur).getName();
-                }
+        for (final PriceList cur : catalog.getPriceLists().getAllPriceLists()) {
+            final DefaultPriceList curDefaultPriceList = (DefaultPriceList) cur;
+            if (curDefaultPriceList.findPlan(name) != null) {
+                return curDefaultPriceList.getName();
             }
         }
         throw new IllegalStateException("Cannot extract pricelist for plan " + name);
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceList.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceList.java
index 23d83cb..c48295d 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceList.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceList.java
@@ -17,7 +17,7 @@
 package org.killbill.billing.catalog;
 
 import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
 
 import javax.xml.bind.annotation.XmlAccessType;
@@ -29,10 +29,10 @@ import javax.xml.bind.annotation.XmlID;
 import javax.xml.bind.annotation.XmlIDREF;
 
 import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.Plan;
 import org.killbill.billing.catalog.api.PriceList;
 import org.killbill.billing.catalog.api.Product;
 import org.killbill.xmlloader.ValidatingConfig;
-import org.killbill.xmlloader.ValidationError;
 import org.killbill.xmlloader.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
@@ -45,19 +45,19 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
     @XmlElementWrapper(name = "plans", required = false)
     @XmlIDREF
     @XmlElement(name = "plan", required = false)
-    private DefaultPlan[] plans;
+    private CatalogEntityCollection<DefaultPlan> plans;
 
     public DefaultPriceList() {
     }
 
     public DefaultPriceList(final DefaultPlan[] plans, final String name) {
-        this.plans = plans;
+        this.plans = new CatalogEntityCollection(plans);
         this.name = name;
     }
 
     @Override
-    public DefaultPlan[] getPlans() {
-        return plans;
+    public Collection<Plan> getPlans() {
+        return (Collection<Plan>) plans.getEntries();
     }
 
     /* (non-Javadoc)
@@ -73,16 +73,20 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
       */
     @Override
     public DefaultPlan[] findPlans(final Product product, final BillingPeriod period) {
-        final List<DefaultPlan> result = new ArrayList<DefaultPlan>(plans.length);
+        final List<DefaultPlan> result = new ArrayList<DefaultPlan>(plans.size());
         for (final DefaultPlan cur : getPlans()) {
             if (cur.getProduct().equals(product) &&
-                    (cur.getRecurringBillingPeriod() != null && cur.getRecurringBillingPeriod().equals(period))) {
+                (cur.getRecurringBillingPeriod() != null && cur.getRecurringBillingPeriod().equals(period))) {
                 result.add(cur);
             }
         }
         return result.toArray(new DefaultPlan[result.size()]);
     }
 
+    public DefaultPlan findPlan(final String planName) {
+        return plans.findByName(planName);
+    }
+
     @Override
     public ValidationErrors validate(final StandaloneCatalog catalog, final ValidationErrors errors) {
         return errors;
@@ -94,7 +98,7 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
     }
 
     public DefaultPriceList setPlans(final DefaultPlan[] plans) {
-        this.plans = plans;
+        this.plans = new CatalogEntityCollection(plans);
         return this;
     }
 
@@ -112,17 +116,16 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
         if (name != null ? !name.equals(that.name) : that.name != null) {
             return false;
         }
-        if (!Arrays.equals(plans, that.plans)) {
+        if (!plans.equals(that.plans)) {
             return false;
         }
-
         return true;
     }
 
     @Override
     public int hashCode() {
         int result = name != null ? name.hashCode() : 0;
-        result = 31 * result + (plans != null ? Arrays.hashCode(plans) : 0);
+        result = 31 * result + (plans != null ? plans.hashCode() : 0);
         return result;
     }
 }
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java
index a2795e3..e58c8ca 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java
@@ -19,6 +19,7 @@ package org.killbill.billing.catalog;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Date;
 import java.util.List;
 
@@ -77,14 +78,14 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 
     @XmlElementWrapper(name = "products", required = false)
     @XmlElement(name = "product", required = false)
-    private DefaultProduct[] products;
+    private CatalogEntityCollection<DefaultProduct> products;
 
     @XmlElement(name = "rules", required = true)
     private DefaultPlanRules planRules;
 
     @XmlElementWrapper(name = "plans", required = false)
     @XmlElement(name = "plan", required = false)
-    private DefaultPlan[] plans;
+    private CatalogEntityCollection<DefaultPlan> plans;
 
     @XmlElement(name = "priceLists", required = true)
     private DefaultPriceListSet priceLists;
@@ -121,7 +122,16 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
      */
     @Override
     public DefaultProduct[] getCurrentProducts() {
-        return products;
+        return (DefaultProduct[]) products.toArray(new DefaultProduct[products.size()]);
+    }
+
+    public Collection<DefaultProduct> getAllProducts() {
+        return products.getEntries();
+    }
+
+
+    public Collection<DefaultPlan> getAllPlans() {
+        return plans.getEntries();
     }
 
     /* (non-Javadoc)
@@ -139,12 +149,12 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 
     @Override
     public DefaultPlan[] getCurrentPlans() {
-        return plans;
+        return (DefaultPlan[])  plans.toArray(new DefaultPlan[plans.size()]);
     }
 
     public boolean isTemplateCatalog() {
-        return (products == null || products.length == 0) &&
-               (plans == null || plans.length == 0) &&
+        return (products == null || products.size() == 0) &&
+               (plans == null || plans.size() == 0) &&
                (supportedCurrencies == null || supportedCurrencies.length == 0);
     }
 
@@ -198,10 +208,9 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
         if (name == null || plans == null) {
             throw new CatalogApiException(ErrorCode.CAT_NO_SUCH_PLAN, name);
         }
-        for (final DefaultPlan p : plans) {
-            if (p.getName().equals(name)) {
-                return p;
-            }
+        final DefaultPlan result = plans.findByName(name);
+        if (result != null) {
+            return result;
         }
         throw new CatalogApiException(ErrorCode.CAT_NO_SUCH_PLAN, name);
     }
@@ -211,10 +220,9 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
         if (name == null || products == null) {
             throw new CatalogApiException(ErrorCode.CAT_NO_SUCH_PRODUCT, name);
         }
-        for (final DefaultProduct p : products) {
-            if (p.getName().equals(name)) {
-                return p;
-            }
+        final Product result = products.findByName(name);
+        if (result != null) {
+            return result;
         }
         throw new CatalogApiException(ErrorCode.CAT_NO_SUCH_PRODUCT, name);
     }
@@ -224,7 +232,6 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
         if (name == null || plans == null) {
             throw new CatalogApiException(ErrorCode.CAT_NO_SUCH_PHASE, name);
         }
-
         final String planName = DefaultPlanPhase.planName(name);
         final Plan plan = findCurrentPlan(planName);
         return plan.findPhase(name);
@@ -236,7 +243,6 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
         if (name == null || priceLists == null) {
             throw new CatalogApiException(ErrorCode.CAT_PRICE_LIST_NOT_FOUND, name);
         }
-
         return priceLists.findPriceListFrom(name);
     }
 
@@ -278,8 +284,8 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 
     @Override
     public ValidationErrors validate(final StandaloneCatalog catalog, final ValidationErrors errors) {
-        validateCollection(catalog, errors, products);
-        validateCollection(catalog, errors, plans);
+        validateCollection(catalog, errors, (DefaultProduct[])  products.toArray(new DefaultProduct[products.size()]));
+        validateCollection(catalog, errors, (DefaultPlan[])  plans.toArray(new DefaultPlan[plans.size()]));
         priceLists.validate(catalog, errors);
         planRules.validate(catalog, errors);
         return errors;
@@ -313,7 +319,7 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
     }
 
     public StandaloneCatalog setProducts(final DefaultProduct[] products) {
-        this.products = products;
+        this.products = new CatalogEntityCollection<DefaultProduct>(products);
         return this;
     }
 
@@ -323,7 +329,7 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
     }
 
     public StandaloneCatalog setPlans(final DefaultPlan[] plans) {
-        this.plans = plans;
+        this.plans = new CatalogEntityCollection<DefaultPlan>(plans);
         return this;
     }
 
@@ -391,7 +397,6 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
         } catch (CatalogApiException e) {
             // No such product - just return an empty list
         }
-
         return availAddons;
     }
 
@@ -437,13 +442,13 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
         if (planRules != null ? !planRules.equals(that.planRules) : that.planRules != null) {
             return false;
         }
-        if (!Arrays.equals(plans, that.plans)) {
+        if (!plans.equals(that.plans)) {
             return false;
         }
         if (priceLists != null ? !priceLists.equals(that.priceLists) : that.priceLists != null) {
             return false;
         }
-        if (!Arrays.equals(products, that.products)) {
+        if (!products.equals(that.products)) {
             return false;
         }
         if (recurringBillingMode != that.recurringBillingMode) {
@@ -455,7 +460,6 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
         if (!Arrays.equals(units, that.units)) {
             return false;
         }
-
         return true;
     }
 
@@ -466,9 +470,9 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
         result = 31 * result + (recurringBillingMode != null ? recurringBillingMode.hashCode() : 0);
         result = 31 * result + (supportedCurrencies != null ? Arrays.hashCode(supportedCurrencies) : 0);
         result = 31 * result + (units != null ? Arrays.hashCode(units) : 0);
-        result = 31 * result + (products != null ? Arrays.hashCode(products) : 0);
+        result = 31 * result + (products != null ? products.hashCode() : 0);
         result = 31 * result + (planRules != null ? planRules.hashCode() : 0);
-        result = 31 * result + (plans != null ? Arrays.hashCode(plans) : 0);
+        result = 31 * result + (plans != null ? plans.hashCode() : 0);
         result = 31 * result + (priceLists != null ? priceLists.hashCode() : 0);
         result = 31 * result + (catalogURI != null ? catalogURI.hashCode() : 0);
         return result;
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/MockCatalog.java b/catalog/src/test/java/org/killbill/billing/catalog/MockCatalog.java
index ca6adad..ed7bf4e 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/MockCatalog.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/MockCatalog.java
@@ -16,16 +16,18 @@
 
 package org.killbill.billing.catalog;
 
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.Date;
-import java.util.Set;
+import java.util.LinkedList;
 
 import org.joda.time.DateTime;
-
 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.Catalog;
 import org.killbill.billing.catalog.api.CatalogApiException;
+import org.killbill.billing.catalog.api.CatalogEntity;
 import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.catalog.api.Plan;
 import org.killbill.billing.catalog.api.PlanAlignmentChange;
@@ -235,6 +237,36 @@ public class MockCatalog extends StandaloneCatalog implements Catalog {
         return canCreatePlan;
     }
 
+    @Override
+    public DefaultProduct[] getCurrentProducts() {
+        final Collection<DefaultProduct> unordered = super.getAllProducts();
+        final  DefaultProduct[] result = new DefaultProduct[unordered.size()];
+        convertCurrentEntries(unordered, result);
+        return result;
+    }
+
+
+    @Override
+    public DefaultPlan[] getCurrentPlans() {
+        final Collection<DefaultPlan> unordered = super.getAllPlans();
+        final DefaultPlan[] result = new DefaultPlan[unordered.size()];
+        convertCurrentEntries(unordered, result);
+        return result;
+    }
+
+
+    private <T extends CatalogEntity> void convertCurrentEntries(final Collection<T> unordered, final T [] result) {
+        // Tests are not so well written and make assumption on how such entries are ordered
+        final LinkedList<T> list = new LinkedList<T>(unordered);
+        Collections.sort(list, new Comparator<T>() {
+            @Override
+            public int compare(final T o1, final T o2) {
+                return o1.getName().compareTo(o2.getName());
+            }
+        });
+        list.toArray(result);
+    }
+
     public void setCanCreatePlan(final boolean canCreatePlan) {
         this.canCreatePlan = canCreatePlan;
     }
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/MockPlan.java b/catalog/src/test/java/org/killbill/billing/catalog/MockPlan.java
index e77c761..1781de8 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/MockPlan.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/MockPlan.java
@@ -19,7 +19,7 @@ package org.killbill.billing.catalog;
 public class MockPlan extends DefaultPlan {
 
     public static MockPlan createBicycleTrialEvergreen1USD(final int trialDurationInDays) {
-        return new MockPlan("BicycleTrialEvergreen1USD",
+        return new MockPlan("1-BicycleTrialEvergreen1USD",
                             MockProduct.createBicycle(),
                             new DefaultPlanPhase[]{MockPlanPhase.createTrial(trialDurationInDays)},
                             MockPlanPhase.create1USDMonthlyEvergreen(),
@@ -27,7 +27,7 @@ public class MockPlan extends DefaultPlan {
     }
 
     public static MockPlan createBicycleTrialEvergreen1USD() {
-        return new MockPlan("BicycleTrialEvergreen1USD",
+        return new MockPlan("1-BicycleTrialEvergreen1USD",
                             MockProduct.createBicycle(),
                             new DefaultPlanPhase[]{MockPlanPhase.create30DayTrial()},
                             MockPlanPhase.create1USDMonthlyEvergreen(),
@@ -35,7 +35,7 @@ public class MockPlan extends DefaultPlan {
     }
 
     public static MockPlan createSportsCarTrialEvergreen100USD() {
-        return new MockPlan("SportsCarTrialEvergreen100USD",
+        return new MockPlan("4-SportsCarTrialEvergreen100USD",
                             MockProduct.createSportsCar(),
                             new DefaultPlanPhase[]{MockPlanPhase.create30DayTrial()},
                             MockPlanPhase.createUSDMonthlyEvergreen("100.00", null),
@@ -43,7 +43,7 @@ public class MockPlan extends DefaultPlan {
     }
 
     public static MockPlan createPickupTrialEvergreen10USD() {
-        return new MockPlan("PickupTrialEvergreen10USD",
+        return new MockPlan("3-PickupTrialEvergreen10USD",
                             MockProduct.createPickup(),
                             new DefaultPlanPhase[]{MockPlanPhase.create30DayTrial()},
                             MockPlanPhase.createUSDMonthlyEvergreen("10.00", null),
@@ -51,7 +51,7 @@ public class MockPlan extends DefaultPlan {
     }
 
     public static MockPlan createJetTrialEvergreen1000USD() {
-        return new MockPlan("JetTrialEvergreen1000USD",
+        return new MockPlan("5-JetTrialEvergreen1000USD",
                             MockProduct.createJet(),
                             new DefaultPlanPhase[]{MockPlanPhase.create30DayTrial()},
                             MockPlanPhase.create1USDMonthlyEvergreen(),
@@ -59,7 +59,7 @@ public class MockPlan extends DefaultPlan {
     }
 
     public static MockPlan createJetTrialFixedTermEvergreen1000USD() {
-        return new MockPlan("JetTrialEvergreen1000USD",
+        return new MockPlan("6-JetTrialEvergreen1000USD",
                             MockProduct.createJet(),
                             new DefaultPlanPhase[]{MockPlanPhase.create30DayTrial(), MockPlanPhase.createUSDMonthlyFixedTerm("500.00", null, 6)},
                             MockPlanPhase.create1USDMonthlyEvergreen(),
@@ -67,7 +67,7 @@ public class MockPlan extends DefaultPlan {
     }
 
     public static MockPlan createHornMonthlyNoTrial1USD() {
-        return new MockPlan("Horn1USD",
+        return new MockPlan("7-Horn1USD",
                             MockProduct.createHorn(),
                             new DefaultPlanPhase[]{},
                             MockPlanPhase.create1USDMonthlyEvergreen(),
@@ -75,7 +75,7 @@ public class MockPlan extends DefaultPlan {
     }
 
     public MockPlan() {
-        this("BicycleTrialEvergreen1USD",
+        this("1-BicycleTrialEvergreen1USD",
              MockProduct.createBicycle(),
              new DefaultPlanPhase[]{MockPlanPhase.create30DayTrial()},
              MockPlanPhase.create1USDMonthlyEvergreen(),
@@ -96,7 +96,7 @@ public class MockPlan extends DefaultPlan {
     }
 
     public static MockPlan createBicycleNoTrialEvergreen1USD() {
-        return new MockPlan("BicycleNoTrialEvergreen1USD",
+        return new MockPlan("2-BicycleNoTrialEvergreen1USD",
                             MockProduct.createBicycle(),
                             new DefaultPlanPhase[]{},
                             MockPlanPhase.createUSDMonthlyEvergreen("1.0", null),
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/MockProduct.java b/catalog/src/test/java/org/killbill/billing/catalog/MockProduct.java
index f0a718e..6014d43 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/MockProduct.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/MockProduct.java
@@ -33,23 +33,23 @@ public class MockProduct extends DefaultProduct {
     }
 
     public static MockProduct createBicycle() {
-        return new MockProduct("Bicycle", ProductCategory.BASE, "Vehcles");
+        return new MockProduct("1-Bicycle", ProductCategory.BASE, "Vehcles");
     }
 
     public static MockProduct createPickup() {
-        return new MockProduct("Pickup", ProductCategory.BASE, "Vehcles");
+        return new MockProduct("2-Pickup", ProductCategory.BASE, "Vehcles");
     }
 
     public static MockProduct createSportsCar() {
-        return new MockProduct("SportsCar", ProductCategory.BASE, "Vehcles");
+        return new MockProduct("3-SportsCar", ProductCategory.BASE, "Vehcles");
     }
 
     public static MockProduct createJet() {
-        return new MockProduct("Jet", ProductCategory.BASE, "Vehcles");
+        return new MockProduct("4-Jet", ProductCategory.BASE, "Vehcles");
     }
 
     public static MockProduct createHorn() {
-        return new MockProduct("Horn", ProductCategory.ADD_ON, "Vehcles");
+        return new MockProduct("5-Horn", ProductCategory.ADD_ON, "Vehcles");
     }
 
     public static MockProduct createSpotlight() {
@@ -57,7 +57,7 @@ public class MockProduct extends DefaultProduct {
     }
 
     public static MockProduct createRedPaintJob() {
-        return new MockProduct("RedPaintJob", ProductCategory.ADD_ON, "Vehcles");
+        return new MockProduct("6-RedPaintJob", ProductCategory.ADD_ON, "Vehcles");
     }
 
     public static DefaultProduct[] createAll() {
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogUpdater.java b/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogUpdater.java
index 6f2af55..8b98de5 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogUpdater.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogUpdater.java
@@ -20,7 +20,6 @@ package org.killbill.billing.catalog;
 import java.io.ByteArrayInputStream;
 import java.math.BigDecimal;
 import java.net.URI;
-import java.net.URISyntaxException;
 import java.nio.charset.Charset;
 
 import org.joda.time.DateTime;
@@ -62,8 +61,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
         assertEquals(catalog.getCurrentPlans().length, 0);
     }
 
-
-        @Test(groups = "fast")
+    @Test(groups = "fast")
     public void testAddNoTrialPlanOnFirstCatalog() throws CatalogApiException {
 
         final DateTime now = clock.getUTCNow();
@@ -282,7 +280,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "        <currency>GBP</currency>\n" +
                                    "    </currencies>\n" +
                                    "    <products>\n" +
-                                   "        <product name=\"Standard\">\n" +
+                                   "        <product name=\"Dynamic\">\n" +
                                    "            <category>BASE</category>\n" +
                                    "            <included/>\n" +
                                    "            <available/>\n" +
@@ -294,13 +292,13 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "            <available/>\n" +
                                    "            <limits/>\n" +
                                    "        </product>\n" +
-                                   "        <product name=\"Super\">\n" +
+                                   "        <product name=\"Standard\">\n" +
                                    "            <category>BASE</category>\n" +
                                    "            <included/>\n" +
                                    "            <available/>\n" +
                                    "            <limits/>\n" +
                                    "        </product>\n" +
-                                   "        <product name=\"Dynamic\">\n" +
+                                   "        <product name=\"Super\">\n" +
                                    "            <category>BASE</category>\n" +
                                    "            <included/>\n" +
                                    "            <available/>\n" +
@@ -340,13 +338,13 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "        </priceList>\n" +
                                    "    </rules>\n" +
                                    "    <plans>\n" +
-                                   "        <plan name=\"standard-monthly\">\n" +
-                                   "            <product>Standard</product>\n" +
+                                   "        <plan name=\"dynamic-annual\">\n" +
+                                   "            <product>Dynamic</product>\n" +
                                    "            <initialPhases>\n" +
                                    "                <phase type=\"TRIAL\">\n" +
                                    "                    <duration>\n" +
                                    "                        <unit>DAYS</unit>\n" +
-                                   "                        <number>30</number>\n" +
+                                   "                        <number>14</number>\n" +
                                    "                    </duration>\n" +
                                    "                    <fixed type=\"ONE_TIME\">\n" +
                                    "                        <fixedPrice>\n" +
@@ -354,10 +352,6 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "<currency>USD</currency>\n" +
                                    "<value>0</value>\n" +
                                    "                            </price>\n" +
-                                   "                            <price>\n" +
-                                   "<currency>GBP</currency>\n" +
-                                   "<value>0</value>\n" +
-                                   "                            </price>\n" +
                                    "                        </fixedPrice>\n" +
                                    "                    </fixed>\n" +
                                    "                    <usages/>\n" +
@@ -372,12 +366,8 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "                    <billingPeriod>MONTHLY</billingPeriod>\n" +
                                    "                    <recurringPrice>\n" +
                                    "                        <price>\n" +
-                                   "                            <currency>GBP</currency>\n" +
-                                   "                            <value>75.00</value>\n" +
-                                   "                        </price>\n" +
-                                   "                        <price>\n" +
                                    "                            <currency>USD</currency>\n" +
-                                   "                            <value>100.00</value>\n" +
+                                   "                            <value>10</value>\n" +
                                    "                        </price>\n" +
                                    "                    </recurringPrice>\n" +
                                    "                </recurring>\n" +
@@ -430,8 +420,8 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "            </finalPhase>\n" +
                                    "            <plansAllowedInBundle>-1</plansAllowedInBundle>\n" +
                                    "        </plan>\n" +
-                                   "        <plan name=\"super-monthly\">\n" +
-                                   "            <product>Super</product>\n" +
+                                   "        <plan name=\"standard-monthly\">\n" +
+                                   "            <product>Standard</product>\n" +
                                    "            <initialPhases>\n" +
                                    "                <phase type=\"TRIAL\">\n" +
                                    "                    <duration>\n" +
@@ -463,11 +453,11 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "                    <recurringPrice>\n" +
                                    "                        <price>\n" +
                                    "                            <currency>GBP</currency>\n" +
-                                   "                            <value>750.00</value>\n" +
+                                   "                            <value>75.00</value>\n" +
                                    "                        </price>\n" +
                                    "                        <price>\n" +
                                    "                            <currency>USD</currency>\n" +
-                                   "                            <value>1000.00</value>\n" +
+                                   "                            <value>100.00</value>\n" +
                                    "                        </price>\n" +
                                    "                    </recurringPrice>\n" +
                                    "                </recurring>\n" +
@@ -475,13 +465,13 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "            </finalPhase>\n" +
                                    "            <plansAllowedInBundle>-1</plansAllowedInBundle>\n" +
                                    "        </plan>\n" +
-                                   "        <plan name=\"dynamic-annual\">\n" +
-                                   "            <product>Dynamic</product>\n" +
+                                   "        <plan name=\"super-monthly\">\n" +
+                                   "            <product>Super</product>\n" +
                                    "            <initialPhases>\n" +
                                    "                <phase type=\"TRIAL\">\n" +
                                    "                    <duration>\n" +
                                    "                        <unit>DAYS</unit>\n" +
-                                   "                        <number>14</number>\n" +
+                                   "                        <number>30</number>\n" +
                                    "                    </duration>\n" +
                                    "                    <fixed type=\"ONE_TIME\">\n" +
                                    "                        <fixedPrice>\n" +
@@ -489,6 +479,10 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "<currency>USD</currency>\n" +
                                    "<value>0</value>\n" +
                                    "                            </price>\n" +
+                                   "                            <price>\n" +
+                                   "<currency>GBP</currency>\n" +
+                                   "<value>0</value>\n" +
+                                   "                            </price>\n" +
                                    "                        </fixedPrice>\n" +
                                    "                    </fixed>\n" +
                                    "                    <usages/>\n" +
@@ -503,8 +497,12 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "                    <billingPeriod>MONTHLY</billingPeriod>\n" +
                                    "                    <recurringPrice>\n" +
                                    "                        <price>\n" +
+                                   "                            <currency>GBP</currency>\n" +
+                                   "                            <value>750.00</value>\n" +
+                                   "                        </price>\n" +
+                                   "                        <price>\n" +
                                    "                            <currency>USD</currency>\n" +
-                                   "                            <value>10</value>\n" +
+                                   "                            <value>1000.00</value>\n" +
                                    "                        </price>\n" +
                                    "                    </recurringPrice>\n" +
                                    "                </recurring>\n" +
@@ -516,10 +514,10 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "    <priceLists>\n" +
                                    "        <defaultPriceList name=\"DEFAULT\">\n" +
                                    "            <plans>\n" +
-                                   "                <plan>standard-monthly</plan>\n" +
+                                   "                <plan>dynamic-annual</plan>\n" +
                                    "                <plan>sports-monthly</plan>\n" +
+                                   "                <plan>standard-monthly</plan>\n" +
                                    "                <plan>super-monthly</plan>\n" +
-                                   "                <plan>dynamic-annual</plan>\n" +
                                    "            </plans>\n" +
                                    "        </defaultPriceList>\n" +
                                    "    </priceLists>\n" +