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);