killbill-memoizeit

Changes

Details

diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
index b85f6f3..dc33209 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
@@ -227,7 +227,7 @@ public class BusinessSubscription
 
     static BigDecimal getMrrFromISubscription(final IDuration duration, final BigDecimal price)
     {
-        if (duration == null || duration.getUnit() == null || duration.getLength() == 0) {
+        if (duration == null || duration.getUnit() == null || duration.getNumber() == 0) {
             return null;
         }
 
@@ -235,13 +235,13 @@ public class BusinessSubscription
             return BigDecimal.ZERO;
         }
         else if (duration.getUnit().equals(TimeUnit.DAYS)) {
-            return price.multiply(DAYS_IN_MONTH).multiply(BigDecimal.valueOf(duration.getLength()));
+            return price.multiply(DAYS_IN_MONTH).multiply(BigDecimal.valueOf(duration.getNumber()));
         }
         else if (duration.getUnit().equals(TimeUnit.MONTHS)) {
-            return price.divide(BigDecimal.valueOf(duration.getLength()), Rounder.SCALE, BigDecimal.ROUND_HALF_UP);
+            return price.divide(BigDecimal.valueOf(duration.getNumber()), Rounder.SCALE, BigDecimal.ROUND_HALF_UP);
         }
         else if (duration.getUnit().equals(TimeUnit.YEARS)) {
-            return price.divide(BigDecimal.valueOf(duration.getLength()), Rounder.SCALE, RoundingMode.HALF_UP).divide(MONTHS_IN_YEAR, Rounder.SCALE, RoundingMode.HALF_UP);
+            return price.divide(BigDecimal.valueOf(duration.getNumber()), Rounder.SCALE, RoundingMode.HALF_UP).divide(MONTHS_IN_YEAR, Rounder.SCALE, RoundingMode.HALF_UP);
         }
         else {
             log.error("Unknown duration [" + duration + "], can't compute mrr");
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockDuration.java b/analytics/src/test/java/com/ning/billing/analytics/MockDuration.java
index a56a3a5..7eb191e 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockDuration.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockDuration.java
@@ -32,7 +32,7 @@ public class MockDuration
             }
 
             @Override
-            public int getLength()
+            public int getNumber()
             {
                 return 1;
             }
@@ -50,7 +50,7 @@ public class MockDuration
             }
 
             @Override
-            public int getLength()
+            public int getNumber()
             {
                 return 1;
             }
@@ -68,7 +68,7 @@ public class MockDuration
             }
 
             @Override
-            public int getLength()
+            public int getNumber()
             {
                 return 1;
             }
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java b/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
index 5075a92..4912957 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockPhase.java
@@ -16,6 +16,9 @@
 
 package com.ning.billing.analytics;
 
+import java.math.BigDecimal;
+import java.util.Date;
+
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.catalog.api.IDuration;
@@ -25,8 +28,6 @@ import com.ning.billing.catalog.api.IPlanPhase;
 import com.ning.billing.catalog.api.IPrice;
 import com.ning.billing.catalog.api.PhaseType;
 
-import java.math.BigDecimal;
-
 public class MockPhase implements IPlanPhase
 {
     private final PhaseType cohort;
@@ -58,6 +59,11 @@ public class MockPhase implements IPlanPhase
             {
                 return BigDecimal.valueOf(price);
             }
+
+			@Override
+			public Date getEffectiveDateForExistingSubscriptons() {
+				return new Date();
+			}
         };
     }
 
@@ -77,6 +83,11 @@ public class MockPhase implements IPlanPhase
             {
                 return BigDecimal.valueOf(price);
             }
+            
+			@Override
+			public Date getEffectiveDateForExistingSubscriptons() {
+				return new Date();
+			}
         };
     }
 
diff --git a/api/src/main/java/com/ning/billing/catalog/api/IDuration.java b/api/src/main/java/com/ning/billing/catalog/api/IDuration.java
index 45973df..9a2205f 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/IDuration.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/IDuration.java
@@ -20,6 +20,6 @@ public interface IDuration {
 
 	public abstract TimeUnit getUnit();
 
-	public abstract int getLength();
+	public abstract int getNumber();
 
 }
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/catalog/api/IInternationalPrice.java b/api/src/main/java/com/ning/billing/catalog/api/IInternationalPrice.java
index e20ed97..47b206c 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/IInternationalPrice.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/IInternationalPrice.java
@@ -17,6 +17,7 @@
 package com.ning.billing.catalog.api;
 
 import java.math.BigDecimal;
+import java.util.Date;
 
 
 public interface IInternationalPrice {
@@ -25,4 +26,6 @@ public interface IInternationalPrice {
 
 	public abstract BigDecimal getPrice(Currency currency);
 
+	public abstract Date getEffectiveDateForExistingSubscriptons();
+
 }
\ No newline at end of file
diff --git a/catalog/src/main/java/com/ning/billing/catalog/Duration.java b/catalog/src/main/java/com/ning/billing/catalog/Duration.java
index ac34cf6..af55806 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Duration.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Duration.java
@@ -32,7 +32,7 @@ public class Duration extends ValidatingConfig<Catalog> implements IDuration {
 
 	@XmlElement(required=false)
     private Integer number = -1;
-
+	
     /* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IDuration#getUnit()
 	 */
@@ -45,23 +45,25 @@ public class Duration extends ValidatingConfig<Catalog> implements IDuration {
 	 * @see com.ning.billing.catalog.IDuration#getLength()
 	 */
     @Override
-	public int getLength() {
+	public int getNumber() {
         return number;
     }
 
-    public void setUnit(TimeUnit unit) {
-		this.unit = unit;
-	}
-
-	public void setLength(int length) {
-		this.number = length;
-	}
-
-
-
 	@Override
 	public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
+		//TODO MDW - Validation TimeUnit UNLIMITED iff number == -1
 		return errors;
+	}
+
+	protected Duration setUnit(TimeUnit unit) {
+		this.unit = unit;
+		return this;
+	}
 
+	protected Duration setNumber(Integer number) {
+		this.number = number;
+		return this;
 	}
+	
+	
 }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/InternationalPrice.java b/catalog/src/main/java/com/ning/billing/catalog/InternationalPrice.java
index c81c9b7..63cf388 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/InternationalPrice.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/InternationalPrice.java
@@ -49,8 +49,12 @@ public class InternationalPrice extends ValidatingConfig<Catalog> implements IIn
 		return prices;
 	}
 
-	public void setPrices(Price[] prices) {
-		this.prices = prices;
+	/* (non-Javadoc)
+	 * @see com.ning.billing.catalog.IInternationalPrice#getEffectiveDateForExistingSubscriptons()
+	 */
+	@Override
+	public Date getEffectiveDateForExistingSubscriptons() {
+		return effectiveDateForExistingSubscriptons;
 	}
 
 	/* (non-Javadoc)
@@ -88,13 +92,15 @@ public class InternationalPrice extends ValidatingConfig<Catalog> implements IIn
 		}
 		return false;
 	}
-
-	public Date getEffectiveDateForExistingSubscriptons() {
-		return effectiveDateForExistingSubscriptons;
-	}
-
-	public void setEffectiveDateForExistingSubscriptons(
+	
+	protected void setEffectiveDateForExistingSubscriptons(
 			Date effectiveDateForExistingSubscriptons) {
 		this.effectiveDateForExistingSubscriptons = effectiveDateForExistingSubscriptons;
 	}
+
+	protected InternationalPrice setPrices(Price[] prices) {
+		this.prices = prices;
+		return this;
+	}
+
 }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/Plan.java b/catalog/src/main/java/com/ning/billing/catalog/Plan.java
index 92a2e06..9a994f0 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Plan.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Plan.java
@@ -60,27 +60,6 @@ public class Plan extends ValidatingConfig<Catalog> implements IPlan {
 	//A value of -1 means unlimited
 	@XmlElement(required=false)
 	private Integer plansAllowedInBundle = 1;
-	
-	public Plan(){}
-	
-	public Plan(String name, Product product, PlanPhase finalPhase) {
-		this.name = name;
-		this.product = product;
-		this.finalPhase = finalPhase;
-	}
-
-	@Override
-	public void initialize(Catalog catalog, URI sourceURI) {
-		super.initialize(catalog, sourceURI);
-		if(finalPhase != null) {
-			finalPhase.setPlan(this);
-		}
-		if(initialPhases != null) {
-			for(PlanPhase p : initialPhases) {
-				p.setPlan(this);
-			}
-		}
-	}
 
 	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IPlan#getPhases()
@@ -98,15 +77,6 @@ public class Plan extends ValidatingConfig<Catalog> implements IPlan {
         return product;
     }
 
-	public void setInitialPhases(PlanPhase[] phases) {
-		this.initialPhases = phases;
-		
-	}
-
-	public void setProduct(Product product) {
-		this.product = product;
-	}
-
 	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IPlan#getName()
 	 */
@@ -114,12 +84,25 @@ public class Plan extends ValidatingConfig<Catalog> implements IPlan {
 	public String getName() {
 		return name;
 	}
-
-	public void setName(String name) {
-		this.name = name;
+	@Override
+	public PlanPhase getFinalPhase() {
+		return finalPhase;
+	}
+	
+	@Override
+	public BillingPeriod getBillingPeriod(){
+		return finalPhase.getBillingPeriod();
 	}
 
 	/* (non-Javadoc)
+	 * @see com.ning.billing.catalog.IPlan#getPlansAllowedInBundle()
+	 */
+	@Override
+	public int getPlansAllowedInBundle() {
+		return plansAllowedInBundle;
+	}
+	
+	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IPlan#getPhaseIterator()
 	 */
 	@Override
@@ -132,33 +115,48 @@ public class Plan extends ValidatingConfig<Catalog> implements IPlan {
 	}
 	
 	@Override
+	public void initialize(Catalog catalog, URI sourceURI) {
+		super.initialize(catalog, sourceURI);
+		if(finalPhase != null) {
+			finalPhase.setPlan(this);
+		}
+		if(initialPhases != null) {
+			for(PlanPhase p : initialPhases) {
+				p.setPlan(this);
+			}
+		}
+	}
+
+	@Override
 	public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
 		return errors;
 	}
 	
-	@Override
-	public PlanPhase getFinalPhase() {
-		return finalPhase;
+
+	protected Plan setName(String name) {
+		this.name = name;
+		return this;
+	}
+	
+	protected Plan setPlansAllowedInBundle(int plansAllowedInBundle) {
+		this.plansAllowedInBundle = plansAllowedInBundle;
+		return this;		
 	}
 
-	public void setFinalPhase(PlanPhase finalPhase) {
+	protected Plan setFinalPhase(PlanPhase finalPhase) {
 		this.finalPhase = finalPhase;
+		return this;		
 	}
 	
-	@Override
-	public BillingPeriod getBillingPeriod(){
-		return finalPhase.getBillingPeriod();
+	protected Plan setProduct(Product product) {
+		this.product = product;
+		return this;		
 	}
 
-	/* (non-Javadoc)
-	 * @see com.ning.billing.catalog.IPlan#getPlansAllowedInBundle()
-	 */
-	@Override
-	public int getPlansAllowedInBundle() {
-		return plansAllowedInBundle;
+	protected Plan setInitialPhases(PlanPhase[] phases) {
+		this.initialPhases = phases;
+		return this;		
 	}
 
-	public void setPlansAllowedInBundle(int plansAllowedInBundle) {
-		this.plansAllowedInBundle = plansAllowedInBundle;
-	}
+
 }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/PlanPhase.java b/catalog/src/main/java/com/ning/billing/catalog/PlanPhase.java
index 6d9630b..851ef12 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PlanPhase.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PlanPhase.java
@@ -28,6 +28,7 @@ import com.ning.billing.catalog.api.IPlan;
 import com.ning.billing.catalog.api.IPlanPhase;
 import com.ning.billing.catalog.api.PhaseType;
 import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationError;
 import com.ning.billing.util.config.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
@@ -39,7 +40,7 @@ public class PlanPhase extends ValidatingConfig<Catalog> implements IPlanPhase {
     @XmlElement(required=true)
     private Duration duration;
     
-    @XmlElement(required=false)
+    @XmlElement(required=true)
     private BillingPeriod billingPeriod = BillingPeriod.NO_BILLING_PERIOD;
 
 	@XmlElement(required=false)
@@ -48,18 +49,12 @@ public class PlanPhase extends ValidatingConfig<Catalog> implements IPlanPhase {
 	@XmlElement(required=false)
 	private InternationalPrice fixedPrice;
 
+//  Not supported: variable pricing
 //	@XmlElement(required=false)
 //	private InternationalPrice unitPrice;
 
 	//Not exposed in XML
 	private IPlan plan;
-	
-	public PlanPhase(){}
-
-    public PlanPhase(BillingPeriod period, PhaseType type) {
-		this.billingPeriod = period;
-		this.type = type;
-	}
 
 	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IPlanPhase#getRecurringPrice()
@@ -69,10 +64,6 @@ public class PlanPhase extends ValidatingConfig<Catalog> implements IPlanPhase {
         return recurringPrice;
     }
 
-	public void setReccuringPrice(InternationalPrice price) {
-		this.recurringPrice = price;
-	}
-
 	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IPlanPhase#getInternationalPrice()
 	 */
@@ -81,11 +72,15 @@ public class PlanPhase extends ValidatingConfig<Catalog> implements IPlanPhase {
         return fixedPrice;
     }
 
-	public void setFixedPrice(InternationalPrice price) {
-		this.fixedPrice = price;
+	/* (non-Javadoc)
+	 * @see com.ning.billing.catalog.IPlanPhase#getCohort()
+	 */
+	@Override
+	public PhaseType getPhaseType() {
+		return type;
 	}
 
-    /* (non-Javadoc)
+	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IPlanPhase#getBillCycleDuration()
 	 */
     @Override
@@ -93,10 +88,6 @@ public class PlanPhase extends ValidatingConfig<Catalog> implements IPlanPhase {
     	return billingPeriod;
     }
 
-	public void setBillCycleDuration(BillingPeriod billingPeriod) {
-		this.billingPeriod = billingPeriod;
-	}
-
 	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IPlanPhase#getName()
 	 */
@@ -113,10 +104,6 @@ public class PlanPhase extends ValidatingConfig<Catalog> implements IPlanPhase {
 		return plan;
 	}
 
-	public void setPlan(IPlan plan) {
-		this.plan = plan;
-	}
-
 	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IPlanPhase#getDuration()
 	 */
@@ -125,34 +112,66 @@ public class PlanPhase extends ValidatingConfig<Catalog> implements IPlanPhase {
  		return duration;
 	}
 
-	public void setDuration(Duration duration) {
-		this.duration = duration;
-	}
-
 	@Override
 	public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
+		//Validation: check for nulls
+		if(billingPeriod == null) {
+			errors.add(new ValidationError(String.format("Phase %s of plan %s has a reccurring price but no billing period", type.toString(), plan.getName()), 
+					catalog.getCatalogURI(), PlanPhase.class, type.toString()));
+		}
+		
+		
+		
+		
+		//Validation: if there is a recurring price there must be a billing period
+		if(recurringPrice != null && (billingPeriod == null || billingPeriod ==BillingPeriod.NO_BILLING_PERIOD)) {
+			errors.add(new ValidationError(String.format("Phase %s of plan %s has a reccurring price but no billing period", type.toString(), plan.getName()), 
+					catalog.getCatalogURI(), PlanPhase.class, type.toString()));
+		}
+		//Validation: if there is no reccuring price there should be no billing period
+		if(recurringPrice == null && billingPeriod != BillingPeriod.NO_BILLING_PERIOD) {
+			errors.add(new ValidationError(String.format("Phase %s of plan %s has no reccurring price but does have a billing period. The billing period shoudl be set to '%s'", 
+					type.toString(), plan.getName(), BillingPeriod.NO_BILLING_PERIOD), 
+					catalog.getCatalogURI(), PlanPhase.class, type.toString()));
+		}
+		
 		return errors;
 
 	}
 
-	/* (non-Javadoc)
-	 * @see com.ning.billing.catalog.IPlanPhase#getCohort()
-	 */
-	@Override
-	public PhaseType getPhaseType() {
-		return type;
+	protected PlanPhase setFixedPrice(InternationalPrice price) {
+		this.fixedPrice = price;
+		return this;
 	}
 
-	public void setCohort(PhaseType cohort) {
+	protected PlanPhase setReccuringPrice(InternationalPrice price) {
+		this.recurringPrice = price;
+		return this;
+	}
+
+	protected PlanPhase setPhaseType(PhaseType cohort) {
 		this.type = cohort;
+		return this;
 	}
 
-	public void setBillingPeriod(BillingPeriod billingPeriod) {
+	protected PlanPhase setBillingPeriod(BillingPeriod billingPeriod) {
 		this.billingPeriod = billingPeriod;
+		return this;
+	}
+
+	protected PlanPhase setDuration(Duration duration) {
+		this.duration = duration;
+		return this;
+	}
+
+	protected PlanPhase setPlan(IPlan plan) {
+		this.plan = plan;
+		return this;
 	}
 	
-	//TODO MDW - validation: if there is a recurring price there must be a billing period
-	//TODO MDW - validation: if there is no reccuring price there should be no billing period
-	
+	protected PlanPhase setBillCycleDuration(BillingPeriod billingPeriod) {
+		this.billingPeriod = billingPeriod;
+		return this;
+	}
 
 }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/Price.java b/catalog/src/main/java/com/ning/billing/catalog/Price.java
index 885191e..369b9ac 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Price.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Price.java
@@ -42,9 +42,7 @@ public class Price extends ValidatingConfig<Catalog> implements IPrice {
 	public Currency getCurrency() {
 		return currency;
 	}
-	public void setCurrency(Currency currency) {
-		this.currency = currency;
-	}
+
 	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IPrice#getValue()
 	 */
@@ -52,9 +50,17 @@ public class Price extends ValidatingConfig<Catalog> implements IPrice {
 	public BigDecimal getValue() {
 		return value;
 	}
-	public void setValue(BigDecimal value) {
+	
+	public Price setCurrency(Currency currency) {
+		this.currency = currency;
+		return this;
+	}
+
+	protected Price setValue(BigDecimal value) {
 		this.value = value;
+		return this;
 	}
+	
 	@Override
 	public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
 		return errors;
diff --git a/catalog/src/main/java/com/ning/billing/catalog/Product.java b/catalog/src/main/java/com/ning/billing/catalog/Product.java
index 371c4be..fb2ffb5 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Product.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Product.java
@@ -86,19 +86,6 @@ public class Product extends ValidatingConfig<Catalog> implements IProduct {
         return name;
     }
 
-	public void setName(String name) {
-		this.name = name;
-	}
-
-	public void setCatagory(ProductCategory category) {
-		this.category = category;
-	}
-
-	@Override
-	public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
-		return errors;
-	}
-
 	public boolean isIncluded(Product addon) {
 		for(Product p : included) {
 			if (addon == p) {
@@ -122,7 +109,41 @@ public class Product extends ValidatingConfig<Catalog> implements IProduct {
 		catalogName = catalog.getCalalogName();
 	}
 
+	@Override
+	public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
+		//TODO: MDW validation: inclusion and exclusion lists can only contain addon products
+		//TODO: MDW validation: a given product can only be in, at most, one of inclusion and exclusion lists
+		return errors;
+	}
+
+	protected Product setName(String name) {
+		this.name = name;
+		return this;
+	}
+
+	protected Product setCatagory(ProductCategory category) {
+		this.category = category;
+		return this;
+	}
+
+	protected Product setCategory(ProductCategory category) {
+		this.category = category;
+		return this;
+	}
+
+	protected Product setIncluded(Product[] included) {
+		this.included = included;
+		return this;
+	}
+
+	protected Product setAvailable(Product[] available) {
+		this.available = available;
+		return this;
+	}
+
+	protected Product setCatalogName(String catalogName) {
+		this.catalogName = catalogName;
+		return this;
+	}
 
-	//TODO: MDW validation: inclusion and exclusion lists can only contain addon products
-	//TODO: MDW validation: a given product can only be in, at most, one of inclusion and exclusion lists
 }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java b/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java
index 6665390..d94f625 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/rules/PlanRules.java
@@ -140,7 +140,7 @@ public class PlanRules extends ValidatingConfig<Catalog>  {
 	}
 
 
-	protected void setProductTiers(ProductTier[] productTiers) {
+	public void setProductTiers(ProductTier[] productTiers) {
 		this.productTiers = productTiers;
 	}
 
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java b/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java
new file mode 100644
index 0000000..cd9afbe
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockInternationalPrice.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.catalog;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import com.ning.billing.catalog.api.Currency;
+
+public class MockInternationalPrice extends InternationalPrice {
+	
+	MockInternationalPrice() {
+		setEffectiveDateForExistingSubscriptons(new Date());
+		setPrices(new Price[] {
+			new Price().setCurrency(Currency.USD).setValue(new BigDecimal(1))	
+		});
+	}
+	
+	MockInternationalPrice(Date effectiveDateForExistingSubscriptions, Price[] price) {
+		setEffectiveDateForExistingSubscriptons(effectiveDateForExistingSubscriptions);
+		setPrices(price);
+	}
+
+	MockInternationalPrice(Price... price) {
+		setEffectiveDateForExistingSubscriptons(new Date());
+		setPrices(price);
+	}
+
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java b/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java
new file mode 100644
index 0000000..cf5324d
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockPlan.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.catalog;
+
+public class MockPlan extends Plan {
+
+	public MockPlan(String name, Product product, PlanPhase[] planPhases, PlanPhase finalPhase, int plansAllowedInBundle) {
+		setName(name);
+		setProduct(product);
+		setFinalPhase(finalPhase);
+		setInitialPhases(planPhases);
+		setPlansAllowedInBundle(plansAllowedInBundle);
+	}
+	
+	public MockPlan() {
+		setName("test-plan");
+		setProduct(new MockProduct());
+		setFinalPhase(new MockPlanPhase(this));
+		setInitialPhases(null);
+		setPlansAllowedInBundle(1);
+	}
+
+	public MockPlan(MockPlanPhase mockPlanPhase) {
+		setName("test-plan");
+		setProduct(new MockProduct());
+		setFinalPhase(mockPlanPhase);
+		setInitialPhases(null);
+		setPlansAllowedInBundle(1);
+	}
+
+
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockPlanPhase.java b/catalog/src/test/java/com/ning/billing/catalog/MockPlanPhase.java
new file mode 100644
index 0000000..ede4319
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockPlanPhase.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.catalog;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.TimeUnit;
+
+public class MockPlanPhase extends PlanPhase {
+
+    public MockPlanPhase(
+    		BillingPeriod billingPeriod, 
+    		PhaseType type, 
+    		Duration duration, 
+    		InternationalPrice recurringPrice, 
+    		InternationalPrice fixedPrice) {
+		setBillingPeriod(billingPeriod);
+		setPhaseType(type);
+		setDuration(duration);
+		setReccuringPrice(recurringPrice);
+		setFixedPrice(fixedPrice);
+	}
+    
+    public MockPlanPhase() {
+		setBillingPeriod(BillingPeriod.MONTHLY);
+		setPhaseType(PhaseType.EVERGREEN);
+		setDuration(new Duration().setNumber(-1).setUnit(TimeUnit.UNLIMITED));
+		setReccuringPrice(new MockInternationalPrice());
+		setFixedPrice(null);
+		setPlan(new MockPlan(this));
+	}
+
+	public MockPlanPhase(MockPlan mockPlan) {
+		setBillingPeriod(BillingPeriod.MONTHLY);
+		setPhaseType(PhaseType.EVERGREEN);
+		setDuration(new Duration().setNumber(-1).setUnit(TimeUnit.UNLIMITED));
+		setReccuringPrice(new MockInternationalPrice());
+		setFixedPrice(null);
+		setPlan(mockPlan);
+	}
+
+	
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockProduct.java b/catalog/src/test/java/com/ning/billing/catalog/MockProduct.java
new file mode 100644
index 0000000..11620a0
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockProduct.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.catalog;
+
+import com.ning.billing.catalog.api.ProductCategory;
+
+public class MockProduct extends Product {
+
+	public MockProduct() {
+		setName("TestProduct");
+		setCatagory(ProductCategory.BASE);
+		setCatalogName("Ning");
+	}
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java
index 40ed1fe..756b8ea 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCase.java
@@ -24,6 +24,7 @@ import javax.xml.bind.annotation.XmlElement;
 import org.testng.annotations.Test;
 
 import com.ning.billing.catalog.Catalog;
+import com.ning.billing.catalog.MockCatalog;
 import com.ning.billing.catalog.PriceList;
 import com.ning.billing.catalog.Product;
 import com.ning.billing.catalog.api.BillingPeriod;
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java
index beefcfd..49f80e3 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCaseChange.java
@@ -24,6 +24,7 @@ import javax.xml.bind.annotation.XmlElement;
 import org.testng.annotations.Test;
 
 import com.ning.billing.catalog.Catalog;
+import com.ning.billing.catalog.MockCatalog;
 import com.ning.billing.catalog.PriceList;
 import com.ning.billing.catalog.Product;
 import com.ning.billing.catalog.api.BillingPeriod;
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java
index 2fe2f2f..676d460 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/TestCasePhase.java
@@ -24,6 +24,7 @@ import javax.xml.bind.annotation.XmlElement;
 import org.testng.annotations.Test;
 
 import com.ning.billing.catalog.Catalog;
+import com.ning.billing.catalog.MockCatalog;
 import com.ning.billing.catalog.PriceList;
 import com.ning.billing.catalog.Product;
 import com.ning.billing.catalog.api.BillingPeriod;
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java b/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java
new file mode 100644
index 0000000..b38a823
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestPlanPhase.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2010-2011 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.catalog;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.util.config.ValidationErrors;
+
+public class TestPlanPhase {
+	Logger log = LoggerFactory.getLogger(TestPlanPhase.class);
+	
+	@Test(enabled=true)
+	public void testValidation() {
+		log.info("Testing Plan Phase Validation");
+		
+		PlanPhase pp = new MockPlanPhase().setBillCycleDuration(BillingPeriod.MONTHLY).setReccuringPrice(null);
+		ValidationErrors errors = pp.validate(new MockCatalog(), new ValidationErrors());
+		errors.log(log);
+		Assert.assertEquals(errors.size(), 1);
+
+		pp = new MockPlanPhase().setBillCycleDuration(BillingPeriod.NO_BILLING_PERIOD).setReccuringPrice(new MockInternationalPrice());
+		errors = pp.validate(new MockCatalog(), new ValidationErrors());
+		errors.log(log);
+		Assert.assertEquals(errors.size(), 1);
+	}
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java b/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
index 0825eb9..4aedb25 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestPriceListSet.java
@@ -16,6 +16,9 @@
 
 package com.ning.billing.catalog;
 
+import static com.ning.billing.catalog.api.BillingPeriod.*;
+import static com.ning.billing.catalog.api.PhaseType.*;
+
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -30,14 +33,14 @@ public class TestPriceListSet {
 		Product foo = new Product("Foo", ProductCategory.BASE);
 		Product bar = new Product("Bar", ProductCategory.BASE);
 		Plan[] defaultPlans = new Plan[]{ 
-				new Plan("plan-foo-monthly", foo, new PlanPhase(BillingPeriod.MONTHLY, PhaseType.EVERGREEN)),
-				new Plan("plan-bar-monthly", bar, new PlanPhase(BillingPeriod.MONTHLY, PhaseType.EVERGREEN)),
-				new Plan("plan-foo-annual", foo, new PlanPhase(BillingPeriod.ANNUAL, PhaseType.EVERGREEN)),
-				new Plan("plan-bar-annual", bar, new PlanPhase(BillingPeriod.ANNUAL, PhaseType.EVERGREEN))
+				new MockPlan().setName("plan-foo-monthly").setProduct(foo).setFinalPhase(new MockPlanPhase().setBillCycleDuration(MONTHLY).setPhaseType(EVERGREEN)),
+				new MockPlan().setName("plan-bar-monthly").setProduct(bar).setFinalPhase(new MockPlanPhase().setBillCycleDuration(MONTHLY).setPhaseType(EVERGREEN)),
+				new MockPlan().setName("plan-foo-annual").setProduct(foo).setFinalPhase(new MockPlanPhase().setBillCycleDuration(ANNUAL).setPhaseType(EVERGREEN)),
+				new MockPlan().setName("plan-bar-annual").setProduct(bar).setFinalPhase(new MockPlanPhase().setBillCycleDuration(ANNUAL).setPhaseType(EVERGREEN))
 				};
 		Plan[] childPlans = new Plan[]{ 
-				new Plan("plan-foo", foo, new PlanPhase(BillingPeriod.ANNUAL, PhaseType.DISCOUNT)),
-				new Plan("plan-bar", bar, new PlanPhase(BillingPeriod.ANNUAL, PhaseType.DISCOUNT))
+				new MockPlan().setName("plan-foo").setProduct(foo).setFinalPhase(new MockPlanPhase().setBillCycleDuration(ANNUAL).setPhaseType(DISCOUNT)),
+				new MockPlan().setName("plan-bar").setProduct(bar).setFinalPhase(new MockPlanPhase().setBillCycleDuration(ANNUAL).setPhaseType(DISCOUNT))
 				};
 		PriceListDefault defaultPriceList = new PriceListDefault(defaultPlans);
 		PriceList[] childPriceLists = new PriceList[] {
@@ -55,15 +58,16 @@ public class TestPriceListSet {
 		Product foo = new Product("Foo", ProductCategory.BASE);
 		Product bar = new Product("Bar", ProductCategory.BASE);
 		Plan[] defaultPlans = new Plan[]{ 
-				new Plan("plan-foo-monthly", foo, new PlanPhase(BillingPeriod.MONTHLY, PhaseType.EVERGREEN)),
-				new Plan("plan-bar-monthly", bar, new PlanPhase(BillingPeriod.MONTHLY, PhaseType.EVERGREEN)),
-				new Plan("plan-foo-annual", foo, new PlanPhase(null, PhaseType.EVERGREEN)),
-				new Plan("plan-bar-annual", bar, new PlanPhase(null, PhaseType.EVERGREEN))
+				new MockPlan().setName("plan-foo-monthly").setProduct(foo).setFinalPhase(new MockPlanPhase().setBillCycleDuration(MONTHLY).setPhaseType(EVERGREEN)),
+				new MockPlan().setName("plan-bar-monthly").setProduct(bar).setFinalPhase(new MockPlanPhase().setBillCycleDuration(MONTHLY).setPhaseType(EVERGREEN)),
+				new MockPlan().setName("plan-foo-annual").setProduct(foo).setFinalPhase(new MockPlanPhase().setBillCycleDuration(null).setPhaseType(EVERGREEN)),
+				new MockPlan().setName("plan-bar-annual").setProduct(bar).setFinalPhase(new MockPlanPhase().setBillCycleDuration(null).setPhaseType(EVERGREEN))
 				};
 		Plan[] childPlans = new Plan[]{ 
-				new Plan("plan-foo", foo, new PlanPhase(BillingPeriod.ANNUAL, PhaseType.DISCOUNT)),
-				new Plan("plan-bar", bar, new PlanPhase(BillingPeriod.ANNUAL, PhaseType.DISCOUNT))
+				new MockPlan().setName("plan-foo").setProduct(foo).setFinalPhase(new MockPlanPhase().setBillCycleDuration(ANNUAL).setPhaseType(DISCOUNT)),
+				new MockPlan().setName("plan-bar").setProduct(bar).setFinalPhase(new MockPlanPhase().setBillCycleDuration(ANNUAL).setPhaseType(DISCOUNT))
 				};
+
 		PriceListDefault defaultPriceList = new PriceListDefault(defaultPlans);
 		PriceList[] childPriceLists = new PriceList[] {
 				new PriceList(childPlans, "child")
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
index 2214b04..dacf37c 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
@@ -86,6 +86,7 @@
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice> <!-- empty price implies $0 -->
 					</fixedPrice>
 				</phase>
@@ -110,6 +111,7 @@
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice></fixedPrice>
 				    <!-- no price implies $0 -->
 				</phase>
@@ -135,6 +137,7 @@
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
index 7d0e1b8..5e42c30 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
@@ -86,6 +86,7 @@
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice> <!-- empty price implies $0 -->
 					</fixedPrice>
 				</phase>
@@ -110,6 +111,7 @@
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice></fixedPrice>
 				    <!-- no price implies $0 -->
 				</phase>
@@ -135,6 +137,7 @@
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
index 070adbe..cb2a91a 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
@@ -86,6 +86,7 @@
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice> <!-- empty price implies $0 -->
 					</fixedPrice>
 				</phase>
@@ -110,6 +111,7 @@
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice></fixedPrice>
 				    <!-- no price implies $0 -->
 				</phase>
@@ -135,6 +137,7 @@
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
diff --git a/catalog/src/test/resources/WeaponsHire.xml b/catalog/src/test/resources/WeaponsHire.xml
index cfd445b..9ded8fa 100644
--- a/catalog/src/test/resources/WeaponsHire.xml
+++ b/catalog/src/test/resources/WeaponsHire.xml
@@ -167,6 +167,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice> <!-- empty price implies $0 -->
 					</fixedPrice>
 				</phase>
@@ -191,6 +192,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice></fixedPrice>
 				    <!-- no price implies $0 -->
 				</phase>
@@ -216,6 +218,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -240,6 +243,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -264,6 +268,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -288,6 +293,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -312,6 +318,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -348,6 +355,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -384,6 +392,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -463,6 +472,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -487,6 +497,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
diff --git a/catalog/src/test/resources/WeaponsHireSmall.xml b/catalog/src/test/resources/WeaponsHireSmall.xml
index c4a098d..e8150c0 100644
--- a/catalog/src/test/resources/WeaponsHireSmall.xml
+++ b/catalog/src/test/resources/WeaponsHireSmall.xml
@@ -86,6 +86,7 @@
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice> <!-- empty price implies $0 -->
 					</fixedPrice>
 				</phase>
@@ -110,6 +111,7 @@
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice></fixedPrice>
 				    <!-- no price implies $0 -->
 				</phase>
@@ -135,6 +137,7 @@
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
index c087e39..924f1eb 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
@@ -255,7 +255,7 @@ public abstract class TestUserApiBase {
                 return TimeUnit.DAYS;
             }
             @Override
-            public int getLength() {
+            public int getNumber() {
                 return days;
             }
         };
@@ -269,7 +269,7 @@ public abstract class TestUserApiBase {
                 return TimeUnit.MONTHS;
             }
             @Override
-            public int getLength() {
+            public int getNumber() {
                 return months;
             }
         };
@@ -284,7 +284,7 @@ public abstract class TestUserApiBase {
                 return TimeUnit.YEARS;
             }
             @Override
-            public int getLength() {
+            public int getNumber() {
                 return years;
             }
         };
diff --git a/entitlement/src/test/resources/testInput.xml b/entitlement/src/test/resources/testInput.xml
index cfd445b..9ded8fa 100644
--- a/entitlement/src/test/resources/testInput.xml
+++ b/entitlement/src/test/resources/testInput.xml
@@ -167,6 +167,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice> <!-- empty price implies $0 -->
 					</fixedPrice>
 				</phase>
@@ -191,6 +192,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice></fixedPrice>
 				    <!-- no price implies $0 -->
 				</phase>
@@ -216,6 +218,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -240,6 +243,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -264,6 +268,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -288,6 +293,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -312,6 +318,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -348,6 +355,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -384,6 +392,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -463,6 +472,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
@@ -487,6 +497,7 @@ Use Cases to do:
 						<unit>DAYS</unit>
 						<number>30</number>
 					</duration>
+					<billingPeriod>NO_BILLING_PERIOD</billingPeriod>
 					<fixedPrice>
 					</fixedPrice>
 				</phase>
diff --git a/invoice/src/test/java/com/ning/billing/invoice/tests/InternationalPriceMock.java b/invoice/src/test/java/com/ning/billing/invoice/tests/InternationalPriceMock.java
index c2df6ef..2217b6c 100644
--- a/invoice/src/test/java/com/ning/billing/invoice/tests/InternationalPriceMock.java
+++ b/invoice/src/test/java/com/ning/billing/invoice/tests/InternationalPriceMock.java
@@ -21,6 +21,7 @@ import com.ning.billing.catalog.api.IInternationalPrice;
 import com.ning.billing.catalog.api.IPrice;
 
 import java.math.BigDecimal;
+import java.util.Date;
 
 import static org.testng.Assert.fail;
 
@@ -42,4 +43,9 @@ public class InternationalPriceMock implements IInternationalPrice {
     public BigDecimal getPrice(Currency currency) {
         return rate;
     }
+
+	@Override
+	public Date getEffectiveDateForExistingSubscriptons() {
+		return new Date();
+	}
 }
diff --git a/util/src/main/java/com/ning/billing/util/clock/Clock.java b/util/src/main/java/com/ning/billing/util/clock/Clock.java
index 6b5b2f1..43819ba 100644
--- a/util/src/main/java/com/ning/billing/util/clock/Clock.java
+++ b/util/src/main/java/com/ning/billing/util/clock/Clock.java
@@ -44,15 +44,15 @@ public class Clock implements IClock {
         for (IDuration cur : durations) {
             switch (cur.getUnit()) {
             case DAYS:
-                result = result.plusDays(cur.getLength());
+                result = result.plusDays(cur.getNumber());
                 break;
 
             case MONTHS:
-                result = result.plusMonths(cur.getLength());
+                result = result.plusMonths(cur.getNumber());
                 break;
 
             case YEARS:
-                result = result.plusYears(cur.getLength());
+                result = result.plusYears(cur.getNumber());
                 break;
             case UNLIMITED:
             default:
diff --git a/util/src/main/java/com/ning/billing/util/config/ValidationError.java b/util/src/main/java/com/ning/billing/util/config/ValidationError.java
index f2e2346..4a68dac 100644
--- a/util/src/main/java/com/ning/billing/util/config/ValidationError.java
+++ b/util/src/main/java/com/ning/billing/util/config/ValidationError.java
@@ -17,6 +17,8 @@ package com.ning.billing.util.config;
 
 import java.net.URI;
 
+import org.slf4j.Logger;
+
 
 public class ValidationError {
 	private final String description;
@@ -44,5 +46,7 @@ public class ValidationError {
 		return objectName;
 	}
 	
-	
+	public void log(Logger log) {
+		log.error(String.format("%s [%s] (%s:%s)", description, sourceURI, objectType, objectName));
+	}
 }
diff --git a/util/src/main/java/com/ning/billing/util/config/ValidationErrors.java b/util/src/main/java/com/ning/billing/util/config/ValidationErrors.java
index 72cf752..901f636 100644
--- a/util/src/main/java/com/ning/billing/util/config/ValidationErrors.java
+++ b/util/src/main/java/com/ning/billing/util/config/ValidationErrors.java
@@ -19,6 +19,8 @@ package com.ning.billing.util.config;
 import java.net.URI;
 import java.util.ArrayList;
 
+import org.slf4j.Logger;
+
 public class ValidationErrors extends ArrayList<ValidationError>{
 	private static final long serialVersionUID = 1L;
 
@@ -28,4 +30,10 @@ public class ValidationErrors extends ArrayList<ValidationError>{
 		
 	}
 
+	public void log(Logger log) {
+		for(ValidationError error : this) {
+			error.log(log);
+		}	
+	}
+
 }
\ No newline at end of file
diff --git a/util/src/test/java/com/ning/billing/util/clock/ClockMock.java b/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
index 7e41d1c..eb7216e 100644
--- a/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
+++ b/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
@@ -102,18 +102,18 @@ public class ClockMock extends Clock {
         DateTime result = input;
         for (IDuration cur : deltaFromRealityDuration) {
 
-            int length = cur.getLength();
+            int length = cur.getNumber();
             switch (cur.getUnit()) {
             case DAYS:
-                result = result.plusDays(cur.getLength());
+                result = result.plusDays(cur.getNumber());
                 break;
 
             case MONTHS:
-                result = result.plusMonths(cur.getLength());
+                result = result.plusMonths(cur.getNumber());
                 break;
 
             case YEARS:
-                result = result.plusYears(cur.getLength());
+                result = result.plusYears(cur.getNumber());
                 break;
 
             case UNLIMITED: