killbill-memoizeit

Details

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 fa24752..bbc9485 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Catalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Catalog.java
@@ -63,7 +63,7 @@ public class Catalog extends ValidatingConfig<Catalog> implements ICatalog {
 	private Product[] products;
 
 	@XmlElement(name="rules", required=true)
-    private PlanRules planRules;
+	private PlanRules planRules;
 
 	@XmlElementWrapper(name="plans", required=true)
 	@XmlElement(name="plan", required=true)
@@ -78,163 +78,114 @@ public class Catalog extends ValidatingConfig<Catalog> implements ICatalog {
 		this.effectiveDate = effectiveDate;
 	}
 
-	@Override
-	public void initialize(Catalog catalog, URI sourceURI) {
-		catalogURI = sourceURI;
-		super.initialize(catalog, sourceURI);
-		planRules.initialize(catalog, sourceURI);
-		priceLists.initialize(catalog, sourceURI);
-		for(Product p : products) {
-			p.initialize(catalog, sourceURI);
-		}
-		for(Plan p : plans) {
-			p.initialize(catalog, sourceURI);
-		}
-	}
-
-    /* (non-Javadoc)
+	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.ICatalog#getCalalogName()
 	 */
-    @Override
+	@Override
 	public String getCalalogName() {
 		return catalogName;
 	}
 
-    /* (non-Javadoc)
+	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.ICatalog#getProducts()
 	 */
-    @Override
+	@Override
 	public Product[] getProducts() {
 		return products;
 	}
 
-	public void setProducts(Product[] products) {
-		this.products = products;
-	}
-
- 
-    /* (non-Javadoc)
+	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.ICatalog#getPlan(java.lang.String, java.lang.String)
 	 */
-    @Override
+	@Override
 	public Plan getPlan(String productName, BillingPeriod period, String priceListName) {
-    	IProduct product = getProductFromName(productName);
-    	return priceLists.getPlanListFrom(priceListName, product, period);
-    }
+		IProduct product = getProductFromName(productName);
+		return priceLists.getPlanListFrom(priceListName, product, period);
+	}
 
 	@Override
 	public Currency[] getSupportedCurrencies() {
 		return supportedCurrencies;
 	}
 
-	public void setSupportedCurrencies(Currency[] supportedCurrencies) {
-		this.supportedCurrencies = supportedCurrencies;
+	@Override
+	public Plan[] getPlans() {
+		return plans;
+	}
+	@Override
+	public ActionPolicy getPlanChangePolicy(PlanPhaseSpecifier from, PlanSpecifier to) {
+		return planRules.getPlanChangePolicy(from, to, this);
 	}
 
-	public void setPlanChangeRules(PlanRules planChangeRules) {
-		this.planRules = planChangeRules;
+	@Override
+	public PlanAlignmentChange getPlanChangeAlignment(PlanPhaseSpecifier from, PlanSpecifier to) {
+		return planRules.getPlanChangeAlignment(from, to, this);
 	}
 
 	@Override
-	public Plan[] getPlans() {
-		return plans;
+	public ActionPolicy getPlanCancelPolicy(PlanPhaseSpecifier planPhase) {
+		return planRules.getPlanCancelPolicy(planPhase, this);
 	}
 
-	public void setPlans(Plan[] plans) {
-		this.plans = plans;
+	@Override
+	public PlanAlignmentCreate getPlanCreateAlignment(PlanSpecifier specifier) {
+		return planRules.getPlanCreateAlignment(specifier, this);
 	}
 
 	@Override
-	public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
-		validate(catalog,errors, products);
-		validate(catalog,errors, plans);
-		priceLists.validate(catalog,errors);
-		planRules.validate(catalog, errors);
-		return errors;
+	public BillingAlignment getBillingAlignment(PlanPhaseSpecifier planPhase) {
+		return planRules.getBillingAlignment(planPhase, this);
 	}
 
-    private Collection<? extends ValidationError> validate(Catalog catalog,
-			ValidationErrors errors, ValidatingConfig<Catalog>[] configs) {
-		for(ValidatingConfig<Catalog> config: configs) {
-			
+
+	@Override
+	public Plan getPlanFromName(String name) {
+		if (name == null) {
+			return null;
+		}
+		for(Plan p : plans) {
+			if(p.getName().equals(name)) {
+				return p;
+			}
+		}
+		return null;
+	}
+
+	@Override
+	public IProduct getProductFromName(String name) {
+		for(Product p : products) {
+			if (p.getName().equals(name)) {
+				return p;
+			}
 		}
 		return null;
 	}
 
+
+	@Override
+	public PlanPhase getPhaseFromName(String name) {
+
+		if (name == null) {
+			return null;
+		}
+		for(Plan p : plans) {
+
+			if(p.getFinalPhase().getName().equals(name)) {
+				return p.getFinalPhase();
+			}
+			if (p.getInitialPhases() != null) {
+				for(PlanPhase pp : p.getInitialPhases()) {
+					if(pp.getName().equals(name)) {
+						return pp;
+					}
+				}
+			}
+		}
+
+		return null;
+	}
+
 	@Override
-    public ActionPolicy getPlanChangePolicy(PlanPhaseSpecifier from, PlanSpecifier to) {
-        return planRules.getPlanChangePolicy(from, to, this);
-    }
-    
-    @Override
-    public PlanAlignmentChange getPlanChangeAlignment(PlanPhaseSpecifier from, PlanSpecifier to) {
-        return planRules.getPlanChangeAlignment(from, to, this);
-    }
-
-    @Override
-    public ActionPolicy getPlanCancelPolicy(PlanPhaseSpecifier planPhase) {
-        return planRules.getPlanCancelPolicy(planPhase, this);
-    }
-    
-    @Override
-    public PlanAlignmentCreate getPlanCreateAlignment(PlanSpecifier specifier) {
-        return planRules.getPlanCreateAlignment(specifier, this);
-    }
-    
-    @Override
-    public BillingAlignment getBillingAlignment(PlanPhaseSpecifier planPhase) {
-        return planRules.getBillingAlignment(planPhase, this);
-    }
-
-
-    @Override
-    public Plan getPlanFromName(String name) {
-        if (name == null) {
-            return null;
-        }
-        for(Plan p : plans) {
-        	if(p.getName().equals(name)) {
-        		return p;
-        	}
-        }
-        return null;
-    }
-    
-    @Override
-    public IProduct getProductFromName(String name) {
-        for(Product p : products) {
-        	if (p.getName().equals(name)) {
-        		return p;
-        	}
-        }
-        return null;
-    }
-
-
-    @Override
-    public PlanPhase getPhaseFromName(String name) {
-
-        if (name == null) {
-            return null;
-        }
-        for(Plan p : plans) {
-
-            if(p.getFinalPhase().getName().equals(name)) {
-                return p.getFinalPhase();
-            }
-            if (p.getInitialPhases() != null) {
-                for(PlanPhase pp : p.getInitialPhases()) {
-                    if(pp.getName().equals(name)) {
-                        return pp;
-                    }
-                }
-            }
-        }
-
-        return null;
-    }
-
-    @Override
 	public Date getEffectiveDate() {
 		return effectiveDate;
 	}
@@ -246,7 +197,7 @@ public class Catalog extends ValidatingConfig<Catalog> implements ICatalog {
 	public URI getCatalogURI() {
 		return catalogURI;
 	}
-	
+
 	public PlanRules getPlanRules() { 
 		return planRules;
 	}
@@ -256,12 +207,12 @@ public class Catalog extends ValidatingConfig<Catalog> implements ICatalog {
 	}
 
 	@Override
-    public PlanPhase getPhaseFor(String name, Date date) {
-    	if(getEffectiveDate().getTime() >= date.getTime()){
-    		return getPhaseFromName(name);
-    	}
-    	return null;
-    }
+	public PlanPhase getPhaseFor(String name, Date date) {
+		if(getEffectiveDate().getTime() >= date.getTime()){
+			return getPhaseFromName(name);
+		}
+		return null;
+	}
 
 	public void setPriceLists(PriceListSet priceLists) {
 		this.priceLists = priceLists;
@@ -274,7 +225,7 @@ public class Catalog extends ValidatingConfig<Catalog> implements ICatalog {
 	@Override
 	public void configureEffectiveDate(Date date) {
 		// Nothing to do here this is a method that is only inplemented on VersionedCatalog
-		
+
 	}
 
 	public PriceList getPriceListFromName(String priceListName) {
@@ -286,7 +237,58 @@ public class Catalog extends ValidatingConfig<Catalog> implements ICatalog {
 			throws IllegalPlanChange {
 		return planRules.planChange(from, to, this);
 	}
+
+	@Override
+	public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
+		validate(catalog,errors, products);
+		validate(catalog,errors, plans);
+		priceLists.validate(catalog,errors);
+		planRules.validate(catalog, errors);
+		return errors;
+	}
+
+	private Collection<? extends ValidationError> validate(Catalog catalog,
+			ValidationErrors errors, ValidatingConfig<Catalog>[] configs) {
+		for(ValidatingConfig<Catalog> config: configs) {
+
+		}
+		return null;
+	}
 	
-	//TODO: MDW validation - only allow one default pricelist
+
+	@Override
+	public void initialize(Catalog catalog, URI sourceURI) {
+		catalogURI = sourceURI;
+		super.initialize(catalog, sourceURI);
+		planRules.initialize(catalog, sourceURI);
+		priceLists.initialize(catalog, sourceURI);
+		for(Product p : products) {
+			p.initialize(catalog, sourceURI);
+		}
+		for(Plan p : plans) {
+			p.initialize(catalog, sourceURI);
+		}
+	}
+
+
+	protected Catalog setProducts(Product[] products) {
+		this.products = products;
+		return this;
+	}
+	protected Catalog setSupportedCurrencies(Currency[] supportedCurrencies) {
+		this.supportedCurrencies = supportedCurrencies;
+		return this;
+	}
+
+	protected Catalog setPlanChangeRules(PlanRules planChangeRules) {
+		this.planRules = planChangeRules;
+		return this;
+	}
+
+	protected Catalog setPlans(Plan[] plans) {
+		this.plans = plans;
+		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 4a64900..26960b5 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/InternationalPrice.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/InternationalPrice.java
@@ -32,13 +32,12 @@ import com.ning.billing.util.config.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
 public class InternationalPrice extends ValidatingConfig<Catalog> implements IInternationalPrice {
-
 	private static Price[] zeroPrice;
 
 	//TODO MDW Validation - effectiveDateForExistingSubscriptons > catalog effectiveDate 
 	@XmlElement(required=false)
 	private Date effectiveDateForExistingSubscriptons;
-	
+
 	//TODO: Must have a price point for every configured currency
 	//TODO: No prices is a zero cost plan
 	@XmlElement(name="price")
@@ -64,7 +63,7 @@ public class InternationalPrice extends ValidatingConfig<Catalog> implements IIn
 	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.IInternationalPrice#getPrice(com.ning.billing.catalog.api.Currency)
 	 */
-	@Override
+	@Override 
 	public BigDecimal getPrice(Currency currency) {
 		// Note if there are no prices specified we default to 0 for any currency
 		for(IPrice p : prices) {
@@ -85,31 +84,9 @@ public class InternationalPrice extends ValidatingConfig<Catalog> implements IIn
 		this.prices = prices;
 		return this;
 	}
-	
 
 
 	@Override
-	public void initialize(Catalog root, URI uri) {
-		if(prices == null) {
-			prices = getZeroPrice(root);
-		}
-		super.initialize(root, uri);
-	}
-	
-	private synchronized Price[] getZeroPrice(Catalog root) {
-		if(zeroPrice == null) {
-			Currency[] currencies = root.getSupportedCurrencies();
-			zeroPrice = new Price[currencies.length];
-			for(int i = 0; i < currencies.length; i++) {
-				prices[i] = new Price();
-				prices[i].setCurrency(currencies[i]);
-				prices[i].setValue(new BigDecimal(0));
-			}
-		}
-		return zeroPrice;
-	}
-
-	@Override
 	public ValidationErrors validate(Catalog catalog, ValidationErrors errors)  {
 		if(prices.length == 0) return errors;
 		Currency[] supportedCurrencies = catalog.getSupportedCurrencies();
@@ -130,8 +107,27 @@ public class InternationalPrice extends ValidatingConfig<Catalog> implements IIn
 		}
 		return false;
 	}
-	
 
 
+	@Override
+	public void initialize(Catalog root, URI uri) {
+		if(prices == null) {
+			prices = getZeroPrice(root);
+		}
+		super.initialize(root, uri);
+	}
+
+	private synchronized Price[] getZeroPrice(Catalog root) {
+		if(zeroPrice == null) {
+			Currency[] currencies = root.getSupportedCurrencies();
+			zeroPrice = new Price[currencies.length];
+			for(int i = 0; i < currencies.length; i++) {
+				zeroPrice[i] = new Price();
+				zeroPrice[i].setCurrency(currencies[i]);
+				zeroPrice[i].setValue(new BigDecimal(0));
+			}
+		}
+		return zeroPrice;
+	}
 
 }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java b/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
index 2085567..9c1aaf9 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/io/VersionedCatalogLoader.java
@@ -23,10 +23,16 @@ import java.net.MalformedURLException;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLConnection;
+import java.net.URLDecoder;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Scanner;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
 
 import javax.xml.bind.JAXBException;
 import javax.xml.transform.TransformerException;
@@ -60,35 +66,32 @@ public class VersionedCatalogLoader implements ICatalogLoader  {
 	@Override
 	public  VersionedCatalog load(String urlString) throws ServiceException{
 		try {
-			return load(new URL(urlString));
+			List<URL> xmlURLs = null;
+			
+			if(urlString.endsWith(XML_EXTENSION)) { //assume its an xml file
+				xmlURLs = new ArrayList<URL>();
+	        	xmlURLs.add(new URL(urlString));
+			} else { //assume its a directory
+				String[] directoryContents = getResourceListing(urlString);
+				xmlURLs = findXmlReferences(directoryContents, url);
+			}
+			
+			VersionedCatalog result = new VersionedCatalog();
+			for(URL u : xmlURLs) {
+				Catalog catalog = XMLLoader.getObjectFromURL(u, Catalog.class);
+				result.add(catalog);
+			}
+			Date now = clock.getUTCNow().toDate();
+			result.configureEffectiveDate(now);
+			return result;
 		} catch (Exception e) {
 			throw new ServiceException("Problem encountered loading catalog", e);
 		}
 	}
 
-	public  VersionedCatalog load(URL url) throws IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException {
-		List<URL> xmlURLs = null;
-		
-		if(url.getPath().endsWith(XML_EXTENSION)) { //assume its an xml file
-			xmlURLs = new ArrayList<URL>();
-        	xmlURLs.add(url);
-		} else { //assume its a directory
-			String directoryContents = pullContentsFrom(url);
-			xmlURLs = findXmlReferences(directoryContents, url);
-		}
-		
-		VersionedCatalog result = new VersionedCatalog();
-		for(URL u : xmlURLs) {
-			Catalog catalog = XMLLoader.getObjectFromURL(u, Catalog.class);
-			result.add(catalog);
-		}
-		Date now = clock.getUTCNow().toDate();
-		result.configureEffectiveDate(now);
-		return result;
-	}
 	
 	protected  List<URL> findXmlReferences(String directoryContents, URL url) throws MalformedURLException {
-		if(url.getProtocol().equals("file")) {
+		if(url.getProtocol().equals(PROTOCOL_FOR_FILE)) {
 			return findXmlFileReferences(directoryContents, url);
 		} 
 		return findXmlUrlReferences(directoryContents, url);
@@ -163,4 +166,46 @@ public class VersionedCatalogLoader implements ICatalogLoader  {
 		InputStream content = connection.getInputStream();
 		return new Scanner(content).useDelimiter("\\A").next();
 	}
+//	
+//	private String[] getResourceListing(String path) throws URISyntaxException, IOException {
+//	      URL dirURL = this.getClass().getClassLoader().getResource(path);
+//	      if (dirURL != null && dirURL.getProtocol().equals("file")) {
+//	        /* A file path: easy enough */
+//	        return new File(dirURL.toURI()).list();
+//	      } 
+//
+//	      if (dirURL == null) {
+//	        /* 
+//	         * In case of a jar file, we can't actually find a directory.
+//	         * Have to assume the same jar as clazz.
+//	         */
+//	        String me = clazz.getName().replace(".", "/")+".class";
+//	        dirURL = clazz.getClassLoader().getResource(me);
+//	      }
+//	      
+//	      if (dirURL.getProtocol().equals("jar")) {
+//	        /* A JAR path */
+//	        String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); //strip out only the JAR file
+//	        JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
+//	        Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
+//	        Set<String> result = new HashSet<String>(); //avoid duplicates in case it is a subdirectory
+//	        while(entries.hasMoreElements()) {
+//	          String name = entries.nextElement().getName();
+//	          if (name.startsWith(path)) { //filter according to the path
+//	            String entry = name.substring(path.length());
+//	            int checkSubdir = entry.indexOf("/");
+//	            if (checkSubdir >= 0) {
+//	              // if it is a subdirectory, we just return the directory name
+//	              entry = entry.substring(0, checkSubdir);
+//	            }
+//	            result.add(entry);
+//	          }
+//	        }
+//	        return result.toArray(new String[result.size()]);
+//	      } 
+//	        
+//	      throw new UnsupportedOperationException("Cannot list files for URL "+dirURL);
+//	  }
+
+	
 }
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 369b9ac..cdbf464 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Price.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Price.java
@@ -51,7 +51,7 @@ public class Price extends ValidatingConfig<Catalog> implements IPrice {
 		return value;
 	}
 	
-	public Price setCurrency(Currency currency) {
+	protected Price setCurrency(Currency currency) {
 		this.currency = currency;
 		return this;
 	}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java b/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java
new file mode 100644
index 0000000..a02541d
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestInternationalPrice.java
@@ -0,0 +1,58 @@
+/*
+ * 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.net.URI;
+import java.net.URISyntaxException;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.Currency;
+
+public class TestInternationalPrice {
+  @Test
+  public void testZeroValue() throws URISyntaxException {
+	  Catalog c = new MockCatalog();
+	  c.setSupportedCurrencies(new Currency[]{Currency.GBP, Currency.EUR, Currency.USD, Currency.BRL, Currency.MXN});
+	  InternationalPrice p0 =  new MockInternationalPrice();
+	  p0.setPrices(null);
+	  p0.initialize(c, new URI("foo:bar"));
+	  InternationalPrice p1 =  new MockInternationalPrice();
+	  p1.setPrices(new Price[] {
+			  new Price().setCurrency(Currency.GBP).setValue(new BigDecimal(1)),
+			  new Price().setCurrency(Currency.EUR).setValue(new BigDecimal(1)),
+			  new Price().setCurrency(Currency.USD).setValue(new BigDecimal(1)),
+			  new Price().setCurrency(Currency.BRL).setValue(new BigDecimal(1)),
+			  new Price().setCurrency(Currency.MXN).setValue(new BigDecimal(1)),		  
+	  });
+	  p1.initialize(c, new URI("foo:bar"));
+
+	  Assert.assertEquals(p0.getPrice(Currency.GBP), new BigDecimal(0));
+	  Assert.assertEquals(p0.getPrice(Currency.EUR), new BigDecimal(0));
+	  Assert.assertEquals(p0.getPrice(Currency.USD), new BigDecimal(0));
+	  Assert.assertEquals(p0.getPrice(Currency.BRL), new BigDecimal(0));
+	  Assert.assertEquals(p0.getPrice(Currency.MXN), new BigDecimal(0));
+	  
+	  Assert.assertEquals(p1.getPrice(Currency.GBP), new BigDecimal(1));
+	  Assert.assertEquals(p1.getPrice(Currency.EUR), new BigDecimal(1));
+	  Assert.assertEquals(p1.getPrice(Currency.USD), new BigDecimal(1));
+	  Assert.assertEquals(p1.getPrice(Currency.BRL), new BigDecimal(1));
+	  Assert.assertEquals(p1.getPrice(Currency.MXN), new BigDecimal(1));
+	  
+  }
+}