killbill-memoizeit

Details

diff --git a/api/src/main/java/com/ning/billing/catalog/api/CatalogApiException.java b/api/src/main/java/com/ning/billing/catalog/api/CatalogApiException.java
new file mode 100644
index 0000000..6099e23
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/catalog/api/CatalogApiException.java
@@ -0,0 +1,33 @@
+/*
+ * 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.api;
+
+import com.ning.billing.BillingExceptionBase;
+import com.ning.billing.ErrorCode;
+
+public class CatalogApiException extends BillingExceptionBase {
+	private static final long serialVersionUID = 1L;
+
+	public CatalogApiException(Throwable cause, Object... args) {
+		super(cause, ErrorCode.CAT_ILLEGAL_CHANGE_REQUEST, args);
+	}
+
+	public CatalogApiException(Object... args) {
+		super(ErrorCode.CAT_ILLEGAL_CHANGE_REQUEST, args);
+	}
+
+}
diff --git a/api/src/main/java/com/ning/billing/catalog/api/ICatalog.java b/api/src/main/java/com/ning/billing/catalog/api/ICatalog.java
index 5a5f872..e67c154 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/ICatalog.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/ICatalog.java
@@ -32,6 +32,9 @@ public interface ICatalog {
 	public abstract ActionPolicy getPlanChangePolicy(PlanPhaseSpecifier from,
 			PlanSpecifier to);
 
+	public abstract PlanChangeResult planChange(PlanPhaseSpecifier from,
+			PlanSpecifier to) throws IllegalPlanChange;
+	
     public abstract IPlan getPlanFromName(String name);
 
     public abstract IPlanPhase getPhaseFromName(String name);
diff --git a/api/src/main/java/com/ning/billing/catalog/api/IllegalPlanChange.java b/api/src/main/java/com/ning/billing/catalog/api/IllegalPlanChange.java
new file mode 100644
index 0000000..6255383
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/catalog/api/IllegalPlanChange.java
@@ -0,0 +1,36 @@
+/*
+ * 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.api;
+
+import com.ning.billing.ErrorCode;
+
+public class IllegalPlanChange extends CatalogApiException {
+	private static final long serialVersionUID = 1L;
+
+	public IllegalPlanChange(Throwable cause, ErrorCode code, PlanPhaseSpecifier from,
+			PlanSpecifier to) {
+		super(cause, code, from.getProductName(), from.getBillingPeriod(), from.getPriceListName(), to.getProductName(), to.getBillingPeriod(), to.getPriceListName());
+	}
+
+	public IllegalPlanChange(ErrorCode code, PlanPhaseSpecifier from,
+			PlanSpecifier to) {
+		super(code, from.getProductName(), from.getBillingPeriod(), from.getPriceListName(), to.getProductName(), to.getBillingPeriod(), to.getPriceListName());
+	}
+
+
+}
+
diff --git a/api/src/main/java/com/ning/billing/catalog/api/IPriceList.java b/api/src/main/java/com/ning/billing/catalog/api/IPriceList.java
new file mode 100644
index 0000000..6fe3561
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/catalog/api/IPriceList.java
@@ -0,0 +1,26 @@
+/*
+ * 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.api;
+
+
+public interface IPriceList {
+
+	public abstract String getName();
+
+	public abstract IPlan findPlan(IProduct product, BillingPeriod period);
+
+}
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/catalog/api/PlanChangeResult.java b/api/src/main/java/com/ning/billing/catalog/api/PlanChangeResult.java
new file mode 100644
index 0000000..bbb8e39
--- /dev/null
+++ b/api/src/main/java/com/ning/billing/catalog/api/PlanChangeResult.java
@@ -0,0 +1,40 @@
+/*
+ * 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.api;
+
+public class PlanChangeResult {
+ 
+	private final IPriceList newPriceList;
+	private final ActionPolicy policy;
+	private final PlanAlignmentChange alignment;
+	
+	public PlanChangeResult(IPriceList newPriceList, ActionPolicy policy, PlanAlignmentChange alignment) {
+		super();
+		this.newPriceList = newPriceList;
+		this.policy = policy;
+		this.alignment = alignment;
+	}
+
+	public IPriceList getNewPriceList() {
+		return newPriceList;
+	}
+
+	public ActionPolicy getPolicy() {
+		return policy;
+	}	
+	
+}
diff --git a/api/src/main/java/com/ning/billing/ErrorCode.java b/api/src/main/java/com/ning/billing/ErrorCode.java
index 24ee8c7..5cca8fa 100644
--- a/api/src/main/java/com/ning/billing/ErrorCode.java
+++ b/api/src/main/java/com/ning/billing/ErrorCode.java
@@ -42,7 +42,11 @@ public enum ErrorCode {
     /* Cancellation */
     ENT_CANCEL_BAD_STATE(1031, "Subscription %s is in state %s"),
     /* Un-cancellation */
-    ENT_UNCANCEL_BAD_STATE(1070, "Subscription %s was not in a cancelled state")
+    ENT_UNCANCEL_BAD_STATE(1070, "Subscription %s was not in a cancelled state"),
+    
+    CAT_ILLEGAL_CHANGE_REQUEST(2001, "Attempting to change plan from (product: '%s', billing period: '%s', " +
+    		"pricelist '%s') to (product: '%s', billing period: '%s', pricelist '%s'). This transition is not allowed by catalog rules")
+    
     ;
 
     private int code;

catalog/pom.xml 2(+1 -1)

diff --git a/catalog/pom.xml b/catalog/pom.xml
index 0b6b6a3..db24ca9 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -27,7 +27,7 @@
         <dependency>
             <groupId>com.ning.billing</groupId>
             <artifactId>killbill-api</artifactId>
-        </dependency>
+        </dependency> 
         <dependency>
             <groupId>com.ning.billing</groupId>
             <artifactId>killbill-util</artifactId>
diff --git a/catalog/src/main/java/com/ning/billing/catalog/Catalog.java b/catalog/src/main/java/com/ning/billing/catalog/Catalog.java
index bc6482d..9f5d1f0 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Catalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Catalog.java
@@ -32,6 +32,7 @@ import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.catalog.api.ICatalog;
 import com.ning.billing.catalog.api.IProduct;
+import com.ning.billing.catalog.api.IllegalPlanChange;
 import com.ning.billing.catalog.api.PlanAlignmentChange;
 import com.ning.billing.catalog.api.PlanAlignmentCreate;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
@@ -40,6 +41,7 @@ import com.ning.billing.catalog.rules.PlanRules;
 import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationError;
 import com.ning.billing.util.config.ValidationErrors;
+import com.ning.billing.catalog.api.PlanChangeResult;
 
 @XmlRootElement
 @XmlAccessorType(XmlAccessType.NONE)
@@ -278,6 +280,12 @@ public class Catalog extends ValidatingConfig<Catalog> implements ICatalog {
 	public PriceList getPriceListFromName(String priceListName) {
 		return priceLists.findPriceListFrom(priceListName);
 	}
+
+	@Override
+	public PlanChangeResult planChange(PlanPhaseSpecifier from, PlanSpecifier to)
+			throws IllegalPlanChange {
+		return planRules.planChange(from, to);
+	}
 	
 	//TODO: MDW validation - only allow one default pricelist
 
diff --git a/catalog/src/main/java/com/ning/billing/catalog/PriceList.java b/catalog/src/main/java/com/ning/billing/catalog/PriceList.java
index c4842f9..2ce3ef9 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PriceList.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PriceList.java
@@ -25,12 +25,13 @@ import javax.xml.bind.annotation.XmlID;
 import javax.xml.bind.annotation.XmlIDREF;
 
 import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.IPriceList;
 import com.ning.billing.catalog.api.IProduct;
 import com.ning.billing.util.config.ValidatingConfig;
 import com.ning.billing.util.config.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
-public class PriceList extends ValidatingConfig<Catalog>  {
+public class PriceList extends ValidatingConfig<Catalog> implements IPriceList  {
 
 	@XmlAttribute(required=true)
 	@XmlID
@@ -52,10 +53,18 @@ public class PriceList extends ValidatingConfig<Catalog>  {
 		return plans;
 	}
 	
+	/* (non-Javadoc)
+	 * @see com.ning.billing.catalog.IPriceList#getName()
+	 */
+	@Override
 	public String getName() {
         return name;
     }
 
+	/* (non-Javadoc)
+	 * @see com.ning.billing.catalog.IPriceList#findPlan(com.ning.billing.catalog.api.IProduct, com.ning.billing.catalog.api.BillingPeriod)
+	 */
+	@Override
 	public Plan findPlan(IProduct product, BillingPeriod period) {
         for (Plan cur : getPlans()) {
             if (cur.getProduct().equals(product) && 
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 d94f625..ba6dee8 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
@@ -28,6 +28,7 @@ import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.IProduct;
 import com.ning.billing.catalog.api.PlanAlignmentChange;
 import com.ning.billing.catalog.api.PlanAlignmentCreate;
+import com.ning.billing.catalog.api.PlanChangeResult;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PlanSpecifier;
 import com.ning.billing.util.config.ValidatingConfig;
@@ -83,6 +84,38 @@ public class PlanRules extends ValidatingConfig<Catalog>  {
 		this.createAlignmentCase = createAlignmentCase;
 	}
 
+
+	public PlanAlignmentCreate getPlanCreateAlignment(PlanSpecifier specifier, Catalog catalog) {
+		return Case.getResult(createAlignmentCase, specifier, catalog);      
+    }
+	
+	public ActionPolicy getPlanCancelPolicy(PlanPhaseSpecifier planPhase, Catalog catalog) {
+		return CasePhase.getResult(cancelCase, planPhase, catalog);      
+	}
+
+	public BillingAlignment getBillingAlignment(PlanPhaseSpecifier planPhase, Catalog catalog) {
+		return CasePhase.getResult(billingAlignmentCase, planPhase, catalog);      
+	}
+
+	private int getBillingPeriodIndex(BillingPeriod src) {
+		return src.ordinal();
+	}
+
+
+	public void setProductTiers(ProductTier[] productTiers) {
+		this.productTiers = productTiers;
+	}
+
+	public PlanChangeResult planChange(PlanPhaseSpecifier from, PlanSpecifier to) {
+		//TODO disallow transitions to the same thing you came from
+		return null;
+	}
+	
+	public PlanAlignmentChange getPlanChangeAlignment(PlanPhaseSpecifier from,
+			PlanSpecifier to, Catalog catalog) {
+		return CaseChange.getResult(changeAlignmentCase, from, to, catalog);      
+    }
+
 	public ActionPolicy getPlanChangePolicy(PlanPhaseSpecifier from,
 			PlanSpecifier to, Catalog catalog) {
 		
@@ -118,34 +151,6 @@ public class PlanRules extends ValidatingConfig<Catalog>  {
 		}
 		return 0;
 	}
-	public PlanAlignmentChange getPlanChangeAlignment(PlanPhaseSpecifier from,
-			PlanSpecifier to, Catalog catalog) {
-		return CaseChange.getResult(changeAlignmentCase, from, to, catalog);      
-    }
-
-	public PlanAlignmentCreate getPlanCreateAlignment(PlanSpecifier specifier, Catalog catalog) {
-		return Case.getResult(createAlignmentCase, specifier, catalog);      
-    }
-	
-	public ActionPolicy getPlanCancelPolicy(PlanPhaseSpecifier planPhase, Catalog catalog) {
-		return CasePhase.getResult(cancelCase, planPhase, catalog);      
-	}
-
-	public BillingAlignment getBillingAlignment(PlanPhaseSpecifier planPhase, Catalog catalog) {
-		return CasePhase.getResult(billingAlignmentCase, planPhase, catalog);      
-	}
-
-	private int getBillingPeriodIndex(BillingPeriod src) {
-		return src.ordinal();
-	}
-
-
-	public void setProductTiers(ProductTier[] productTiers) {
-		this.productTiers = productTiers;
-	}
-
-
-
 	
     //TODO: MDW - Validation: check that the plan change special case pairs are unique!
     //TODO: MDW - Validation: check that the each product appears in at most one tier.
diff --git a/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java b/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
index 288c3df..cb447ea 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
@@ -31,8 +31,10 @@ import com.ning.billing.catalog.api.ICatalog;
 import com.ning.billing.catalog.api.IPlan;
 import com.ning.billing.catalog.api.IPlanPhase;
 import com.ning.billing.catalog.api.IProduct;
+import com.ning.billing.catalog.api.IllegalPlanChange;
 import com.ning.billing.catalog.api.PlanAlignmentChange;
 import com.ning.billing.catalog.api.PlanAlignmentCreate;
+import com.ning.billing.catalog.api.PlanChangeResult;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PlanSpecifier;
 import com.ning.billing.util.config.ValidatingConfig;
@@ -181,6 +183,12 @@ public class VersionedCatalog extends ValidatingConfig<Catalog> implements ICata
 	public BillingAlignment getBillingAlignment(PlanPhaseSpecifier planPhase) {
 		return currentCatalog.getBillingAlignment(planPhase);
 	}
+
+	@Override
+	public PlanChangeResult planChange(PlanPhaseSpecifier from, PlanSpecifier to)
+			throws IllegalPlanChange {
+		return currentCatalog.planChange(from, to);
+	}
 	
 	//TODO MDW validation - ensure all catalog versions have a single name
 	//TODO MDW validation - ensure effective dates are different (actually do we want this?)
diff --git a/catalog/src/test/java/com/ning/billing/catalog/rules/MockPlanRules.java b/catalog/src/test/java/com/ning/billing/catalog/rules/MockPlanRules.java
new file mode 100644
index 0000000..6961ffc
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/rules/MockPlanRules.java
@@ -0,0 +1,21 @@
+/*
+ * 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.rules;
+
+public class MockPlanRules extends PlanRules {
+
+}
diff --git a/catalog/src/test/resources/WeaponsHire.xml b/catalog/src/test/resources/WeaponsHire.xml
index 9ded8fa..29b89d2 100644
--- a/catalog/src/test/resources/WeaponsHire.xml
+++ b/catalog/src/test/resources/WeaponsHire.xml
@@ -106,6 +106,37 @@ Use Cases to do:
 			<policy>IMMEDIATE</policy>
 		</changePolicyRule>
 		<changePolicyCase> 
+			<policy>END_OF_TERM</policy>
+		</changePolicyCase>
+		<changePolicyCase> 
+			<toProduct>Assault-Rifle</toProduct>
+			<policy>IMMEDIATE</policy>
+		</changePolicyCase>
+		<changePolicyCase> 
+			<toProduct>Pistol</toProduct>
+			<policy>END_OF_TERM</policy>
+		</changePolicyCase>
+		<changePolicyCase> 
+			<fromProduct>Pistol</fromProduct>
+			<toProduct>Shotgun</toProduct>
+			<policy>IMMEDIATE</policy>
+		</changePolicyCase>
+		<changePolicyCase> 
+			<fromProduct>Assault-Rifle</fromProduct>
+			<toProduct>Shotgun</toProduct>
+			<policy>END_OF_TERM</policy>
+		</changePolicyCase>
+		<changePolicyCase> 
+			<fromBillingPeriod>MONTHLY</fromBillingPeriod>
+			<toBillingPeriod>ANNUAL</toBillingPeriod>
+			<policy>IMMEDIATE</policy>
+		</changePolicyCase>
+		<changePolicyCase> 
+			<fromBillingPeriod>ANNUAL</fromBillingPeriod>
+			<toBillingPeriod>MONTHLY</toBillingPeriod>
+			<policy>END_OF_TERM</policy>
+		</changePolicyCase>
+		<changePolicyCase> 
 			<fromBillingPeriod>MONTHLY</fromBillingPeriod>
 			<toProduct>Assault-Rifle</toProduct>
 			<toBillingPeriod>MONTHLY</toBillingPeriod>