killbill-aplcache

catalog: Initial rework for catalog initialization. See #678 *

12/16/2016 9:10:22 PM

Changes

Details

diff --git a/catalog/src/main/java/org/killbill/billing/catalog/CatalogSafetyInitializer.java b/catalog/src/main/java/org/killbill/billing/catalog/CatalogSafetyInitializer.java
new file mode 100644
index 0000000..996d2f1
--- /dev/null
+++ b/catalog/src/main/java/org/killbill/billing/catalog/CatalogSafetyInitializer.java
@@ -0,0 +1,72 @@
+/*
+ * 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.lang.reflect.Array;
+import java.lang.reflect.Field;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+
+public class CatalogSafetyInitializer {
+
+
+    //
+    // Ensure that all uninitialized arrays for which there is neither a 'required' XmlElementWrapper or XmlElement annotation
+    // end up initialized with a default zero length array (allowing to safely get the length and iterate over (0) element.
+    //
+    public static void initializeNonRequiredArrayFields(final Object obj) {
+        try {
+            final Field[] fields = obj.getClass().getDeclaredFields();
+            for (final Field f : fields) {
+                if (f.getType().isArray()) {
+                    final XmlElementWrapper xmlElementWrapper = f.getAnnotation(XmlElementWrapper.class);
+                    if (xmlElementWrapper != null) {
+                        if (!xmlElementWrapper.required()) {
+                            initializeArrayIfNull(obj, f);
+                        }
+                    } else {
+                        final XmlElement xmlElement = f.getAnnotation(XmlElement.class);
+                        if (xmlElement != null && !xmlElement.required()) {
+                            initializeArrayIfNull(obj, f);
+                        }
+                    }
+                }
+            }
+        } catch (final IllegalAccessException e) {
+            throw new RuntimeException("Failed during catalog initialization : ", e);
+        } catch (final ClassNotFoundException e) {
+            throw new RuntimeException("Failed during catalog initialization : ", e);
+        }
+    }
+
+    private static void initializeArrayIfNull(final Object obj, final Field f) throws IllegalAccessException, ClassNotFoundException {
+        f.setAccessible(true);
+        if (f.get(obj) == null) {
+            f.set(obj, getZeroLengthArrayInitializer(f));
+        }
+        f.setAccessible(false);
+    }
+
+    private static Object[] getZeroLengthArrayInitializer(final Field f) throws ClassNotFoundException {
+        // Yack... type erasure, why?
+        final String arrayClassName = f.getType().getCanonicalName();
+        final Class type = Class.forName(arrayClassName.substring(0, arrayClassName.length() - 2));
+        return (Object[]) Array.newInstance(type, 0);
+    }
+}
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/CatalogUpdater.java b/catalog/src/main/java/org/killbill/billing/catalog/CatalogUpdater.java
index 9055e00..9701a73 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/CatalogUpdater.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/CatalogUpdater.java
@@ -28,6 +28,7 @@ import org.killbill.billing.catalog.api.BillingAlignment;
 import org.killbill.billing.catalog.api.BillingMode;
 import org.killbill.billing.catalog.api.CatalogApiException;
 import org.killbill.billing.catalog.api.Currency;
+import org.killbill.billing.catalog.api.InternationalPrice;
 import org.killbill.billing.catalog.api.PhaseType;
 import org.killbill.billing.catalog.api.Plan;
 import org.killbill.billing.catalog.api.PlanAlignmentChange;
@@ -80,6 +81,8 @@ public class CatalogUpdater {
                 .setPlanRules(getSaneDefaultPlanRules(defaultPriceList));
         if (currencies != null && currencies.length > 0) {
             tmp.setSupportedCurrencies(currencies);
+        } else {
+            tmp.setSupportedCurrencies(new Currency[0]);
         }
         tmp.initialize(tmp, DUMMY_URI);
 
@@ -168,9 +171,7 @@ public class CatalogUpdater {
             evergreenPhase.setRecurring(recurring);
         }
 
-        try {
-            recurring.getRecurringPrice().getPrice(desc.getCurrency());
-        } catch (CatalogApiException ignore) {
+        if (!isPriceForCurrencyExists(recurring.getRecurringPrice(), desc.getCurrency())) {
             catalog.addRecurringPriceToPlan(recurring.getRecurringPrice(), new DefaultPrice().setCurrency(desc.getCurrency()).setValue(desc.getAmount()));
         }
 
@@ -194,6 +195,18 @@ public class CatalogUpdater {
         catalog.initialize(catalog, DUMMY_URI);
     }
 
+    private boolean isPriceForCurrencyExists(final InternationalPrice price, final Currency currency) {
+        if (price.getPrices().length == 0) {
+            return false;
+        }
+        try {
+            price.getPrice(currency);
+        } catch (CatalogApiException ignore) {
+            return false;
+        }
+        return true;
+    }
+
     private void validateExistingPlan(final DefaultPlan plan, final SimplePlanDescriptor desc) throws CatalogApiException {
 
         boolean failedValidation = false;
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultFixed.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultFixed.java
index e1cb95a..1218f4d 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultFixed.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultFixed.java
@@ -62,18 +62,11 @@ public class DefaultFixed extends ValidatingConfig<StandaloneCatalog> implements
 
     @Override
     public void initialize(final StandaloneCatalog root, final URI uri) {
+        super.initialize(root, uri);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+
         if (fixedPrice != null) {
             fixedPrice.initialize(root, uri);
-        } else if (root.getCurrentSupportedCurrencies() != null && root.getCurrentSupportedCurrencies().length > 0){
-            fixedPrice = new DefaultInternationalPrice();
-
-            final DefaultPrice [] tmp = new DefaultPrice[root.getCurrentSupportedCurrencies().length];
-            int i = 0;
-            for (Currency cur : root.getCurrentSupportedCurrencies()) {
-                tmp[i] = new DefaultPrice(BigDecimal.ZERO, cur);
-                i++;
-            }
-            fixedPrice.setPrices(tmp);
         }
     }
 
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultInternationalPrice.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultInternationalPrice.java
index 10040ba..5ff3622 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultInternationalPrice.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultInternationalPrice.java
@@ -36,9 +36,8 @@ import org.killbill.xmlloader.ValidationErrors;
 @XmlAccessorType(XmlAccessType.NONE)
 public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalog> implements InternationalPrice {
 
-    //TODO: Must have a price point for every configured currency
-    //TODO: No prices is a zero cost plan
-    @XmlElement(name = "price")
+    // No prices is a zero cost plan in all currencies
+    @XmlElement(name = "price", required = false)
     private DefaultPrice[] prices;
 
 
@@ -53,14 +52,20 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
     public DefaultInternationalPrice() {}
 
     public DefaultInternationalPrice(final DefaultInternationalPrice in, final PlanPhasePriceOverride override, final boolean fixed) {
-        this.prices = in.getPrices() != null ? new DefaultPrice[in.getPrices().length] : null;
-        // There is a question on whether we keep the other prices that were not overridden or only have one entry for the overridden price on that currency.
-        for (int i = 0; i < in.getPrices().length; i++) {
-            final DefaultPrice curPrice = (DefaultPrice)  in.getPrices()[i];
-            if (curPrice.getCurrency().equals(override.getCurrency())) {
-                prices[i] = new DefaultPrice(fixed ? override.getFixedPrice() : override.getRecurringPrice(), override.getCurrency());
-            } else {
-                prices[i] = curPrice;
+
+        if (in.getPrices().length == 0) {
+            this.prices = new DefaultPrice[1];
+            this.prices[0] = new DefaultPrice(fixed ? override.getFixedPrice() : override.getRecurringPrice(), override.getCurrency());
+        } else {
+            this.prices = new DefaultPrice[in.getPrices().length];
+            // There is a question on whether we keep the other prices that were not overridden or only have one entry for the overridden price on that currency.
+            for (int i = 0; i < in.getPrices().length; i++) {
+                final DefaultPrice curPrice = (DefaultPrice)  in.getPrices()[i];
+                if (curPrice.getCurrency().equals(override.getCurrency())) {
+                    prices[i] = new DefaultPrice(fixed ? override.getFixedPrice() : override.getRecurringPrice(), override.getCurrency());
+                } else {
+                    prices[i] = curPrice;
+                }
             }
         }
     }
@@ -70,6 +75,10 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
       */
     @Override
     public BigDecimal getPrice(final Currency currency) throws CatalogApiException {
+        if (prices.length == 0) {
+            return BigDecimal.ZERO;
+        }
+
         for (final Price p : prices) {
             if (p.getCurrency() == currency) {
                 return p.getValue();
@@ -115,23 +124,10 @@ public class DefaultInternationalPrice extends ValidatingConfig<StandaloneCatalo
 
     @Override
     public void initialize(final StandaloneCatalog root, final URI uri) {
-        if (prices == null) {
-            prices = getZeroPrice(root);
-        }
         super.initialize(root, uri);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
     }
 
-    private synchronized DefaultPrice[] getZeroPrice(final StandaloneCatalog root) {
-        final Currency[] currencies = root.getCurrentSupportedCurrencies();
-        final DefaultPrice[] zeroPrice = new DefaultPrice[currencies.length];
-        for (int i = 0; i < currencies.length; i++) {
-            zeroPrice[i] = new DefaultPrice();
-            zeroPrice[i].setCurrency(currencies[i]);
-            zeroPrice[i].setValue(new BigDecimal(0));
-        }
-
-        return zeroPrice;
-    }
 
     @Override
     public boolean isZero() {
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultLimit.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultLimit.java
index 29390bf..103d209 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultLimit.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultLimit.java
@@ -18,6 +18,8 @@
 
 package org.killbill.billing.catalog;
 
+import java.net.URI;
+
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
@@ -77,6 +79,13 @@ public class DefaultLimit extends ValidatingConfig<StandaloneCatalog> implements
     }
 
     @Override
+    public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
+        super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+    }
+
+
+    @Override
     public boolean compliesWith(double value) {
         if (max != null) {
             if (value > max.doubleValue()) {
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 84fe628..433126a 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlan.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlan.java
@@ -56,7 +56,6 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
     @XmlID
     private String name;
 
-    //TODO MDW Validation - effectiveDateForExistingSubscriptions > catalog effectiveDate
     @XmlElement(required = false)
     private Date effectiveDateForExistingSubscriptions;
 
@@ -129,7 +128,7 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
 
     @Override
     public PlanPhase[] getAllPhases() {
-        final int length = (initialPhases == null || initialPhases.length == 0) ? 1 : (initialPhases.length + 1);
+        final int length = initialPhases.length + 1;
         final PlanPhase[] allPhases = new DefaultPlanPhase[length];
         int cnt = 0;
         if (length > 1) {
@@ -175,19 +174,20 @@ public class DefaultPlan extends ValidatingConfig<StandaloneCatalog> implements 
     @Override
     public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
         super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+
         if (finalPhase != null) {
             finalPhase.setPlan(this);
             finalPhase.initialize(catalog, sourceURI);
         }
-        if (initialPhases != null) {
-            for (final DefaultPlanPhase p : initialPhases) {
-                p.setPlan(this);
-                p.initialize(catalog, sourceURI);
-            }
+        for (final DefaultPlanPhase p : initialPhases) {
+            p.setPlan(this);
+            p.initialize(catalog, sourceURI);
         }
         this.priceListName = this.priceListName  != null ? this.priceListName : findPriceListForPlan(catalog);
     }
 
+
     @Override
     public ValidationErrors validate(final StandaloneCatalog catalog, final ValidationErrors errors) {
         if (effectiveDateForExistingSubscriptions != null &&
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlanPhase.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlanPhase.java
index bf451af..37134ec 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlanPhase.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPlanPhase.java
@@ -155,6 +155,10 @@ public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implem
 
     @Override
     public void initialize(final StandaloneCatalog root, final URI uri) {
+
+        super.initialize(root, uri);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+
         if (fixed != null) {
             fixed.initialize(root, uri);
         }
@@ -163,11 +167,9 @@ public class DefaultPlanPhase extends ValidatingConfig<StandaloneCatalog> implem
             recurring.setPlan(plan);
             recurring.setPhase(this);
         }
-        if (usages != null) {
-            for (DefaultUsage usage : usages) {
-                usage.initialize(root, uri);
-                usage.setPhase(this);
-            }
+        for (DefaultUsage usage : usages) {
+            usage.initialize(root, uri);
+            usage.setPhase(this);
         }
     }
 
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPrice.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPrice.java
index c9e0e96..6b5f6ec 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPrice.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPrice.java
@@ -20,6 +20,7 @@ import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import java.math.BigDecimal;
+import java.net.URI;
 
 import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.catalog.api.CurrencyValueNull;
@@ -77,9 +78,15 @@ public class DefaultPrice extends ValidatingConfig<StandaloneCatalog> implements
     @Override
     public ValidationErrors validate(final StandaloneCatalog catalog, final ValidationErrors errors) {
         return errors;
+    }
 
+    @Override
+    public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
+        super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
     }
 
+
     @Override
     public boolean equals(final Object o) {
         if (this == o) {
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 9bdf070..273f12c 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceList.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceList.java
@@ -16,6 +16,7 @@
 
 package org.killbill.billing.catalog;
 
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -42,7 +43,7 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
     @XmlID
     private String name;
 
-    @XmlElementWrapper(name = "plans", required = false)
+    @XmlElementWrapper(name = "plans", required = true)
     @XmlIDREF
     @XmlElement(type=DefaultPlan.class, name = "plan", required = false)
     private CatalogEntityCollection<Plan> plans;
@@ -97,6 +98,13 @@ public class DefaultPriceList extends ValidatingConfig<StandaloneCatalog> implem
         return errors;
     }
 
+
+    @Override
+    public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
+        super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+    }
+
     public DefaultPriceList setName(final String name) {
         this.name = name;
         return this;
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceListSet.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceListSet.java
index c159833..15a479c 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceListSet.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultPriceListSet.java
@@ -19,6 +19,8 @@ package org.killbill.billing.catalog;
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
+
+import java.net.URI;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -104,6 +106,13 @@ public class DefaultPriceListSet extends ValidatingConfig<StandaloneCatalog> imp
         return errors;
     }
 
+    @Override
+    public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
+        super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+    }
+
+
     public DefaultPriceList getDefaultPricelist() {
         return defaultPricelist;
     }
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultProduct.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultProduct.java
index ffb8e96..bb5ac34 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultProduct.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultProduct.java
@@ -129,7 +129,7 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
     
     
     protected Limit findLimit(String unit) {
-        for(Limit limit: limits) {
+        for (Limit limit: limits) {
             if(limit.getUnit().getName().equals(unit) ) {
                     return limit;
             }
@@ -147,9 +147,14 @@ public class DefaultProduct extends ValidatingConfig<StandaloneCatalog> implemen
     }
 
 
-    
+
     @Override
     public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
+        super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+        for (DefaultLimit cur : limits) {
+            cur.initialize(catalog, sourceURI);
+        }
         catalogName = catalog.getCatalogName();
     }
 
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultRecurring.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultRecurring.java
index 57418b5..f8599bf 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultRecurring.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultRecurring.java
@@ -64,6 +64,8 @@ public class DefaultRecurring extends ValidatingConfig<StandaloneCatalog> implem
 
     @Override
     public void initialize(final StandaloneCatalog root, final URI uri) {
+        super.initialize(root, uri);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
         if (recurringPrice != null) {
             recurringPrice.initialize(root, uri);
         }
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultTier.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultTier.java
index 1baf1a3..1680036 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultTier.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultTier.java
@@ -17,6 +17,7 @@
 
 package org.killbill.billing.catalog;
 
+import java.net.URI;
 import java.util.Arrays;
 
 import javax.xml.bind.annotation.XmlAccessType;
@@ -130,6 +131,14 @@ public class DefaultTier extends ValidatingConfig<StandaloneCatalog> implements 
     }
 
     @Override
+    public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
+        super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+    }
+
+
+
+    @Override
     public boolean equals(final Object o) {
         if (this == o) {
             return true;
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultUnit.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultUnit.java
index a0b2170..c11f6b9 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultUnit.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultUnit.java
@@ -16,6 +16,8 @@
 
 package org.killbill.billing.catalog;
 
+import java.net.URI;
+
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlAttribute;
@@ -45,6 +47,14 @@ public class DefaultUnit extends ValidatingConfig<StandaloneCatalog> implements 
         return errors;
     }
 
+
+    @Override
+    public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
+        super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+    }
+
+
     public DefaultUnit setName(final String name) {
         this.name = name;
         return this;
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/DefaultUsage.java b/catalog/src/main/java/org/killbill/billing/catalog/DefaultUsage.java
index 1c6daa8..cb34f94 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/DefaultUsage.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/DefaultUsage.java
@@ -164,6 +164,9 @@ public class DefaultUsage extends ValidatingConfig<StandaloneCatalog> implements
 
     @Override
     public void initialize(final StandaloneCatalog root, final URI uri) {
+        super.initialize(root, uri);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+
         for (DefaultLimit limit : limits) {
             limit.initialize(root, uri);
         }
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/plugin/StandaloneCatalogMapper.java b/catalog/src/main/java/org/killbill/billing/catalog/plugin/StandaloneCatalogMapper.java
index 37184b7..83f939b 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/plugin/StandaloneCatalogMapper.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/plugin/StandaloneCatalogMapper.java
@@ -76,7 +76,6 @@ import org.killbill.billing.catalog.rules.DefaultPlanRules;
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
 
 public class StandaloneCatalogMapper {
@@ -138,7 +137,7 @@ public class StandaloneCatalogMapper {
             public DefaultCaseChangePlanPolicy apply(final CaseChangePlanPolicy input) {
                 return toDefaultCaseChangePlanPolicy(input);
             }
-        }, true);
+        });
     }
 
     final DefaultCaseChangePlanAlignment[] toDefaultCaseChangePlanAlignments(final Iterable<CaseChangePlanAlignment> input) {
@@ -147,7 +146,7 @@ public class StandaloneCatalogMapper {
             public DefaultCaseChangePlanAlignment apply(final CaseChangePlanAlignment input) {
                 return toDefaultCaseChangePlanAlignment(input);
             }
-        }, true);
+        });
     }
 
     final DefaultCaseBillingAlignment[] toDefaultCaseBillingAlignments(final Iterable<CaseBillingAlignment> input) {
@@ -156,7 +155,7 @@ public class StandaloneCatalogMapper {
             public DefaultCaseBillingAlignment apply(final CaseBillingAlignment input) {
                 return toDefaultCaseBillingAlignment(input);
             }
-        }, true);
+        });
     }
 
     final DefaultCaseCancelPolicy[] toDefaultCaseCancelPolicys(final Iterable<CaseCancelPolicy> input) {
@@ -165,7 +164,7 @@ public class StandaloneCatalogMapper {
             public DefaultCaseCancelPolicy apply(final CaseCancelPolicy input) {
                 return toDefaultCaseCancelPolicy(input);
             }
-        }, true);
+        });
     }
 
     final DefaultCaseCreateAlignment[] toDefaultCaseCreateAlignments(final Iterable<CaseCreateAlignment> input) {
@@ -174,7 +173,7 @@ public class StandaloneCatalogMapper {
             public DefaultCaseCreateAlignment apply(final CaseCreateAlignment input) {
                 return toCaseCreateAlignment(input);
             }
-        }, true);
+        });
     }
 
     final DefaultCasePriceList[] toDefaultCasePriceLists(final Iterable<CasePriceList> input) {
@@ -183,7 +182,7 @@ public class StandaloneCatalogMapper {
             public DefaultCasePriceList apply(final CasePriceList input) {
                 return toDefaultCasePriceList(input);
             }
-        }, true);
+        });
     }
 
     final DefaultCasePriceList toDefaultCasePriceList(final CasePriceList input) {
@@ -318,7 +317,7 @@ public class StandaloneCatalogMapper {
             public DefaultPlanPhase apply(final PlanPhase input) {
                 return toDefaultPlanPhase(input);
             }
-        }, false);
+        });
     }
 
     private DefaultPriceList[] toDefaultPriceLists(final Iterable<PriceList> input) {
@@ -327,7 +326,7 @@ public class StandaloneCatalogMapper {
             public DefaultPriceList apply(final PriceList input) {
                 return toDefaultPriceList(input);
             }
-        }, true);
+        });
     }
 
     private DefaultPrice[] toDefaultPrices(final Iterable<Price> input) {
@@ -336,7 +335,7 @@ public class StandaloneCatalogMapper {
             public DefaultPrice apply(final Price input) {
                 return toDefaultPrice(input);
             }
-        }, false);
+        });
     }
 
     private DefaultUnit[] toDefaultUnits(final Iterable<Unit> input) {
@@ -345,7 +344,7 @@ public class StandaloneCatalogMapper {
             public DefaultUnit apply(final Unit inputTransform) {
                 return toDefaultUnit(inputTransform);
             }
-        }, true);
+        });
     }
 
     private DefaultUnit toDefaultUnit(final Unit input) {
@@ -458,8 +457,8 @@ public class StandaloneCatalogMapper {
         }
     }
 
-    private <I, C extends I> C[] toArrayWithTransform(final Iterable<I> input, final Function<I, C> transformer, boolean returnNullIfNothing) {
-        if (returnNullIfNothing && (input == null || !input.iterator().hasNext())) {
+    private <I, C extends I> C[] toArrayWithTransform(final Iterable<I> input, final Function<I, C> transformer) {
+        if (input == null || !input.iterator().hasNext()) {
             return null;
         }
         final Iterable<C> tmp = Iterables.transform(input, transformer);
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/PriceListDefault.java b/catalog/src/main/java/org/killbill/billing/catalog/PriceListDefault.java
index bc25842..0778ad4 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/PriceListDefault.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/PriceListDefault.java
@@ -16,6 +16,8 @@
 
 package org.killbill.billing.catalog;
 
+import java.net.URI;
+
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 
@@ -45,6 +47,12 @@ public class PriceListDefault extends DefaultPriceList {
     }
 
     @Override
+    public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
+        super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+    }
+
+    @Override
     public String getName() {
         return PriceListSet.DEFAULT_PRICELIST_NAME;
     }
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCase.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCase.java
index de0bef2..319a486 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCase.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCase.java
@@ -17,6 +17,9 @@
 package org.killbill.billing.catalog.rules;
 
 
+import java.net.URI;
+
+import org.killbill.billing.catalog.CatalogSafetyInitializer;
 import org.killbill.billing.catalog.DefaultPrice;
 import org.killbill.billing.catalog.DefaultPriceList;
 import org.killbill.billing.catalog.DefaultProduct;
@@ -92,6 +95,12 @@ public abstract class DefaultCase<T> extends ValidatingConfig<StandaloneCatalog>
         return errors;
     }
 
+    @Override
+    public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
+        super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+    }
+
     protected abstract DefaultCase<T> setProduct(Product product);
 
     protected abstract DefaultCase<T> setProductCategory(ProductCategory productCategory);
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChange.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChange.java
index ea441bd..62a83cb 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChange.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCaseChange.java
@@ -16,11 +16,14 @@
 
 package org.killbill.billing.catalog.rules;
 
+import java.net.URI;
+
 import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlIDREF;
 
+import org.killbill.billing.catalog.CatalogSafetyInitializer;
 import org.killbill.billing.catalog.DefaultPriceList;
 import org.killbill.billing.catalog.DefaultProduct;
 import org.killbill.billing.catalog.StandaloneCatalog;
@@ -149,6 +152,12 @@ public abstract class DefaultCaseChange<T> extends ValidatingConfig<StandaloneCa
         return errors;
     }
 
+    @Override
+    public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
+        super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+    }
+
     public DefaultCaseChange<T> setPhaseType(final PhaseType phaseType) {
         this.phaseType = phaseType;
         return this;
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCasePhase.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCasePhase.java
index cf656ef..d36db6c 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCasePhase.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultCasePhase.java
@@ -16,8 +16,11 @@
 
 package org.killbill.billing.catalog.rules;
 
+import java.net.URI;
+
 import javax.xml.bind.annotation.XmlElement;
 
+import org.killbill.billing.catalog.CatalogSafetyInitializer;
 import org.killbill.billing.catalog.StandaloneCatalog;
 import org.killbill.billing.catalog.api.CatalogApiException;
 import org.killbill.billing.catalog.api.PhaseType;
@@ -57,6 +60,13 @@ public abstract class DefaultCasePhase<T> extends DefaultCaseStandardNaming<T> {
         return errors;
     }
 
+    @Override
+    public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
+        super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+    }
+
+
     public DefaultCasePhase<T> setPhaseType(final PhaseType phaseType) {
         this.phaseType = phaseType;
         return this;
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultPlanRules.java b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultPlanRules.java
index 99efa9c..20c4e9c 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultPlanRules.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/rules/DefaultPlanRules.java
@@ -16,6 +16,7 @@
 
 package org.killbill.billing.catalog.rules;
 
+import java.net.URI;
 import java.util.Arrays;
 
 import javax.xml.bind.annotation.XmlAccessType;
@@ -23,6 +24,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlElementWrapper;
 
+import org.killbill.billing.catalog.CatalogSafetyInitializer;
 import org.killbill.billing.catalog.DefaultPriceList;
 import org.killbill.billing.catalog.StandaloneCatalog;
 import org.killbill.billing.catalog.api.BillingActionPolicy;
@@ -173,6 +175,33 @@ public class DefaultPlanRules extends ValidatingConfig<StandaloneCatalog> implem
         return errors;
     }
 
+
+    @Override
+    public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
+        super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+
+        for (final DefaultCaseChangePlanPolicy cur : changeCase) {
+            cur.initialize(catalog, sourceURI);
+        }
+        for (final DefaultCaseChangePlanAlignment cur : changeAlignmentCase) {
+            cur.initialize(catalog, sourceURI);
+        }
+        for (final DefaultCaseCancelPolicy cur : cancelCase) {
+            cur.initialize(catalog, sourceURI);
+        }
+        for (final DefaultCaseCreateAlignment cur : createAlignmentCase) {
+            cur.initialize(catalog, sourceURI);
+        }
+        for (final DefaultCaseBillingAlignment cur : billingAlignmentCase) {
+            cur.initialize(catalog, sourceURI);
+        }
+        for (final DefaultCasePriceList cur : priceListCase) {
+            cur.initialize(catalog, sourceURI);
+        }
+    }
+
+
     /////////////////////////////////////////////////////////////////////////////////////
     // Setters for testing
     /////////////////////////////////////////////////////////////////////////////////////
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 e6e6cf1..81366e4 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/StandaloneCatalog.java
@@ -68,7 +68,7 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
     @XmlElement(required = true)
     private BillingMode recurringBillingMode;
 
-    @XmlElementWrapper(name = "currencies", required = false)
+    @XmlElementWrapper(name = "currencies", required = true)
     @XmlElement(name = "currency", required = false)
     private Currency[] supportedCurrencies;
 
@@ -76,14 +76,14 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
     @XmlElement(name = "unit", required = false)
     private DefaultUnit[] units;
 
-    @XmlElementWrapper(name = "products", required = false)
+    @XmlElementWrapper(name = "products", required = true)
     @XmlElement(type=DefaultProduct.class, name = "product", required = false)
     private CatalogEntityCollection<Product> products;
 
     @XmlElement(name = "rules", required = true)
     private DefaultPlanRules planRules;
 
-    @XmlElementWrapper(name = "plans", required = false)
+    @XmlElementWrapper(name = "plans", required = true)
     @XmlElement(type=DefaultPlan.class, name = "plan", required = false)
     private CatalogEntityCollection<Plan> plans;
 
@@ -298,10 +298,16 @@ public class StandaloneCatalog extends ValidatingConfig<StandaloneCatalog> imple
 
     @Override
     public void initialize(final StandaloneCatalog catalog, final URI sourceURI) {
-        catalogURI = sourceURI;
+
         super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
+
+        catalogURI = sourceURI;
         planRules.initialize(catalog, sourceURI);
         priceLists.initialize(catalog, sourceURI);
+        for (final DefaultUnit cur : units) {
+            cur.initialize(catalog, sourceURI);
+        }
         for (final Product p : products.getEntries()) {
             ((DefaultProduct)p).initialize(catalog, sourceURI);
         }
diff --git a/catalog/src/main/java/org/killbill/billing/catalog/VersionedCatalog.java b/catalog/src/main/java/org/killbill/billing/catalog/VersionedCatalog.java
index 83f07ac..167bc55 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/VersionedCatalog.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/VersionedCatalog.java
@@ -26,6 +26,8 @@ import java.util.Comparator;
 import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
 
 import javax.annotation.Nullable;
 import javax.xml.bind.annotation.XmlAccessType;
@@ -69,7 +71,11 @@ public class VersionedCatalog extends ValidatingConfig<VersionedCatalog> impleme
     @XmlElementWrapper(name = "versions", required = true)
     @XmlElement(name = "version", required = true)
     private final List<StandaloneCatalog> versions;
+
+    @XmlElement(required = true)
     private String catalogName;
+
+    @XmlElement(required = true)
     private BillingMode recurringBillingMode;
 
     // Required for JAXB deserialization
@@ -400,6 +406,8 @@ public class VersionedCatalog extends ValidatingConfig<VersionedCatalog> impleme
     //
     @Override
     public void initialize(final VersionedCatalog catalog, final URI sourceURI) {
+        super.initialize(catalog, sourceURI);
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(this);
         for (final StandaloneCatalog c : versions) {
             c.initialize(c, sourceURI);
         }
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogSafetyInitializer.java b/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogSafetyInitializer.java
new file mode 100644
index 0000000..26da112
--- /dev/null
+++ b/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogSafetyInitializer.java
@@ -0,0 +1,95 @@
+/*
+ * 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 javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlIDREF;
+
+import org.killbill.billing.catalog.api.Product;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class TestCatalogSafetyInitializer {
+
+    @XmlElementWrapper(name = "initialPhasesWrapperAllRequired", required = true)
+    @XmlElement(name = "phase", required = true)
+    private DefaultPlanPhase[] initialPhasesWrapperAllRequired;
+
+    @XmlElementWrapper(name = "initialPhasesWrapperNotRequired", required = false)
+    @XmlElement(name = "phase", required = false)
+    private DefaultPlanPhase[] initialPhasesWrapperNotRequired;
+
+    @XmlElementWrapper(name = "initialPhasesWrapper", required = true)
+    @XmlElement(name = "phase", required = false)
+    private DefaultPlanPhase[] initialPhasesWrapper;
+
+    @XmlElement(name = "pricesNotRequired", required = false)
+    private DefaultPrice[] pricesNotRequired;
+
+    @XmlElement(name = "prices", required = true)
+    private DefaultPrice[] prices;
+
+    @XmlElementWrapper(name = "available", required = false)
+    @XmlIDREF
+    @XmlElement(type = DefaultProduct.class, name = "addonProduct", required = false)
+    private CatalogEntityCollection<Product> available;
+
+    @Test(groups = "fast")
+    public void testNonRequiredArrayFields() {
+
+        final TestCatalogSafetyInitializer test = new TestCatalogSafetyInitializer();
+        Assert.assertNull(test.getInitialPhasesWrapperAllRequired());
+        Assert.assertNull(test.getInitialPhasesWrapperNotRequired());
+        Assert.assertNull(test.getInitialPhasesWrapper());
+        Assert.assertNull(test.getPricesNotRequired());
+        Assert.assertNull(test.getPrices());
+
+        CatalogSafetyInitializer.initializeNonRequiredArrayFields(test);
+
+        Assert.assertNull(test.getInitialPhasesWrapperAllRequired());
+        Assert.assertNotNull(test.getInitialPhasesWrapperNotRequired());
+        Assert.assertEquals(test.getInitialPhasesWrapperNotRequired().length, 0);
+        Assert.assertNull(test.getInitialPhasesWrapper());
+        Assert.assertNotNull(test.getPricesNotRequired());
+        Assert.assertEquals(test.getPricesNotRequired().length, 0);
+        Assert.assertNull(test.getPrices());
+
+    }
+
+    public DefaultPlanPhase[] getInitialPhasesWrapperAllRequired() {
+        return initialPhasesWrapperAllRequired;
+    }
+
+    public DefaultPlanPhase[] getInitialPhasesWrapperNotRequired() {
+        return initialPhasesWrapperNotRequired;
+    }
+
+    public DefaultPlanPhase[] getInitialPhasesWrapper() {
+        return initialPhasesWrapper;
+    }
+
+    public DefaultPrice[] getPricesNotRequired() {
+        return pricesNotRequired;
+    }
+
+    public DefaultPrice[] getPrices() {
+        return prices;
+    }
+
+}
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 a973ad1..279b914 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogUpdater.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/TestCatalogUpdater.java
@@ -205,7 +205,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
 
         assertEquals(plan.getInitialPhases().length, 1);
         assertEquals(plan.getInitialPhases()[0].getPhaseType(), PhaseType.TRIAL);
-        assertEquals(plan.getInitialPhases()[0].getFixed().getPrice().getPrices().length, 3);
+        assertEquals(plan.getInitialPhases()[0].getFixed().getPrice().getPrices().length, 0);
         assertEquals(plan.getInitialPhases()[0].getFixed().getPrice().getPrice(Currency.EUR), BigDecimal.ZERO);
         assertEquals(plan.getInitialPhases()[0].getName(), "standard-monthly-trial");
 
@@ -279,6 +279,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "        <currency>USD</currency>\n" +
                                    "        <currency>GBP</currency>\n" +
                                    "    </currencies>\n" +
+                                   "    <units/>\n" +
                                    "    <products>\n" +
                                    "        <product name=\"Dynamic\">\n" +
                                    "            <category>BASE</category>\n" +
@@ -384,16 +385,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "                        <number>30</number>\n" +
                                    "                    </duration>\n" +
                                    "                    <fixed type=\"ONE_TIME\">\n" +
-                                   "                        <fixedPrice>\n" +
-                                   "                            <price>\n" +
-                                   "<currency>USD</currency>\n" +
-                                   "<value>0</value>\n" +
-                                   "                            </price>\n" +
-                                   "                            <price>\n" +
-                                   "<currency>GBP</currency>\n" +
-                                   "<value>0</value>\n" +
-                                   "                            </price>\n" +
-                                   "                        </fixedPrice>\n" +
+                                   "                        <fixedPrice/>\n" +
                                    "                    </fixed>\n" +
                                    "                    <usages/>\n" +
                                    "                </phase>\n" +
@@ -429,16 +421,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "                        <number>30</number>\n" +
                                    "                    </duration>\n" +
                                    "                    <fixed type=\"ONE_TIME\">\n" +
-                                   "                        <fixedPrice>\n" +
-                                   "                            <price>\n" +
-                                   "<currency>USD</currency>\n" +
-                                   "<value>0</value>\n" +
-                                   "                            </price>\n" +
-                                   "                            <price>\n" +
-                                   "<currency>GBP</currency>\n" +
-                                   "<value>0</value>\n" +
-                                   "                            </price>\n" +
-                                   "                        </fixedPrice>\n" +
+                                   "                        <fixedPrice/>\n" +
                                    "                    </fixed>\n" +
                                    "                    <usages/>\n" +
                                    "                </phase>\n" +
@@ -474,16 +457,7 @@ public class TestCatalogUpdater extends CatalogTestSuiteNoDB {
                                    "                        <number>30</number>\n" +
                                    "                    </duration>\n" +
                                    "                    <fixed type=\"ONE_TIME\">\n" +
-                                   "                        <fixedPrice>\n" +
-                                   "                            <price>\n" +
-                                   "<currency>USD</currency>\n" +
-                                   "<value>0</value>\n" +
-                                   "                            </price>\n" +
-                                   "                            <price>\n" +
-                                   "<currency>GBP</currency>\n" +
-                                   "<value>0</value>\n" +
-                                   "                            </price>\n" +
-                                   "                        </fixedPrice>\n" +
+                                   "                        <fixedPrice/>\n" +
                                    "                    </fixed>\n" +
                                    "                    <usages/>\n" +
                                    "                </phase>\n" +
diff --git a/catalog/src/test/java/org/killbill/billing/catalog/TestDefaultPriceOverride.java b/catalog/src/test/java/org/killbill/billing/catalog/TestDefaultPriceOverride.java
index 858dde8..278c67b 100644
--- a/catalog/src/test/java/org/killbill/billing/catalog/TestDefaultPriceOverride.java
+++ b/catalog/src/test/java/org/killbill/billing/catalog/TestDefaultPriceOverride.java
@@ -165,17 +165,25 @@ public class TestDefaultPriceOverride extends CatalogTestSuiteWithEmbeddedDB {
         }
     }
 
-    private void assertInternationalPrice(final InternationalPrice newInternationalPrice, final InternationalPrice initInternationalPrice, final PlanPhasePriceOverride override, final boolean isFixed) throws CurrencyValueNull {
-        assertEquals(newInternationalPrice.getPrices().length, initInternationalPrice.getPrices().length);
-        for (int i = 0; i < newInternationalPrice.getPrices().length; i++) {
-            final Price initPrice = initInternationalPrice.getPrices()[i];
-            final Price newPrice = newInternationalPrice.getPrices()[i];
-            if (override != null && override.getCurrency() == initPrice.getCurrency() &&
-                ((isFixed && override.getFixedPrice() != null) || (!isFixed && override.getRecurringPrice() != null))) {
-                assertEquals(newPrice.getValue().compareTo(isFixed ? override.getFixedPrice() : override.getRecurringPrice()), 0);
-            } else {
-                if (initPrice != null && initPrice.getValue() != null) {
-                    assertEquals(newPrice.getValue().compareTo(initPrice.getValue()), 0);
+    private void assertInternationalPrice(final InternationalPrice newInternationalPrice, final InternationalPrice initInternationalPrice, final PlanPhasePriceOverride override, final boolean isFixed) throws CatalogApiException {
+
+        if (initInternationalPrice.getPrices().length == 0) {
+            if (override != null) {
+                assertEquals(newInternationalPrice.getPrices().length, 1);
+                assertEquals(newInternationalPrice.getPrice(override.getCurrency()).compareTo(isFixed ? override.getFixedPrice() : override.getRecurringPrice()), 0);
+            }
+        } else {
+            assertEquals(newInternationalPrice.getPrices().length, initInternationalPrice.getPrices().length);
+            for (int i = 0; i < newInternationalPrice.getPrices().length; i++) {
+                final Price initPrice = initInternationalPrice.getPrices()[i];
+                final Price newPrice = newInternationalPrice.getPrices()[i];
+                if (override != null && override.getCurrency() == initPrice.getCurrency() &&
+                    ((isFixed && override.getFixedPrice() != null) || (!isFixed && override.getRecurringPrice() != null))) {
+                    assertEquals(newPrice.getValue().compareTo(isFixed ? override.getFixedPrice() : override.getRecurringPrice()), 0);
+                } else {
+                    if (initPrice != null && initPrice.getValue() != null) {
+                        assertEquals(newPrice.getValue().compareTo(initPrice.getValue()), 0);
+                    }
                 }
             }
         }
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/CatalogJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/CatalogJson.java
index 2056d6e..381089a 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/CatalogJson.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/CatalogJson.java
@@ -137,10 +137,8 @@ public class CatalogJson {
 
     private List<UsageJson> buildUsagesJson(final Usage[] usages) throws CurrencyValueNull {
         List<UsageJson> usagesJson = new ArrayList<UsageJson>();
-        if (usages != null && usages.length > 0) {
-            for (int i=0; i < usages.length; i++) {
-                usagesJson.add(new UsageJson(usages[i].getBillingPeriod().toString(), buildTiers(usages[i].getTiers())));
-            }
+        for (int i = 0; i < usages.length; i++) {
+            usagesJson.add(new UsageJson(usages[i].getBillingPeriod().toString(), buildTiers(usages[i].getTiers())));
         }
         return usagesJson;
     }
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PlanDetailJson.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PlanDetailJson.java
index 0b8249c..371d9f3 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PlanDetailJson.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/json/PlanDetailJson.java
@@ -67,7 +67,7 @@ public class PlanDetailJson {
             if (plan.getFinalPhase() == null ||
                 plan.getFinalPhase().getRecurring() == null ||
                 plan.getFinalPhase().getRecurring().getRecurringPrice() == null ||
-                plan.getFinalPhase().getRecurring().getRecurringPrice().getPrices() == null) {
+                plan.getFinalPhase().getRecurring().getRecurringPrice().getPrices().length == 0) {
                 this.finalPhaseRecurringPrice = ImmutableList.<PriceJson>of();
             } else {
                 this.finalPhaseRecurringPrice = Lists.transform(ImmutableList.<Price>copyOf(plan.getFinalPhase().getRecurring().getRecurringPrice().getPrices()),
diff --git a/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultBillingEvent.java b/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultBillingEvent.java
index 7183e3c..9b500aa 100644
--- a/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultBillingEvent.java
+++ b/junction/src/main/java/org/killbill/billing/junction/plumbing/billing/DefaultBillingEvent.java
@@ -340,7 +340,7 @@ public class DefaultBillingEvent implements BillingEvent {
         if (!isActive) {
             return result;
         }
-        if (planPhase != null && planPhase.getUsages() != null) {
+        if (planPhase != null && planPhase.getUsages().length > 0) {
             result = Lists.newArrayList();
             for (Usage usage : planPhase.getUsages()) {
                 result.add(usage);