killbill-memoizeit

Merge branch 'irs-integration' of github.com:ning/killbill

11/8/2011 12:23:48 AM

Changes

catalog/pom.xml 27(+4 -23)

catalog/src/main/java/com/ning/billing/catalog/ValidatingConfig.java 60(+0 -60)

invoice/pom.xml 5(+4 -1)

Details

catalog/pom.xml 27(+4 -23)

diff --git a/catalog/pom.xml b/catalog/pom.xml
index 24e9ea2..f82753a 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -29,6 +29,10 @@
             <artifactId>killbill-api</artifactId>
         </dependency>
         <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-util</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.testng</groupId>
             <artifactId>testng</artifactId>
             <scope>test</scope>
@@ -40,27 +44,4 @@
         </dependency>
     </dependencies>
     
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>exec-maven-plugin</artifactId>
-                <version>1.1.1</version>
-                <executions>
-                    <execution>
-                        <phase>test</phase>
-                        <goals>
-                            <goal>java</goal>
-                        </goals>
-                        <configuration>
-                            <mainClass>com.ning.billing.catalog.io.XMLSchemaGenerator</mainClass>
-                            <arguments>
-                                <argument>${project.basedir}/src/test/resources</argument>
-                            </arguments>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
 </project>
diff --git a/catalog/src/main/java/com/ning/billing/catalog/Case.java b/catalog/src/main/java/com/ning/billing/catalog/Case.java
index 2d92df0..24b6fff 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Case.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Case.java
@@ -22,8 +22,10 @@ import javax.xml.bind.annotation.XmlIDREF;
 import com.ning.billing.catalog.api.BillingPeriod;
 import com.ning.billing.catalog.api.PlanSpecifier;
 import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
 
-public abstract class Case<T> extends ValidatingConfig {
+public abstract class Case<T> extends ValidatingConfig<Catalog> {
 
 	@XmlElement(required=false)
 	@XmlIDREF
diff --git a/catalog/src/main/java/com/ning/billing/catalog/CaseChange.java b/catalog/src/main/java/com/ning/billing/catalog/CaseChange.java
index 5eabc70..3efaa2e 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/CaseChange.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/CaseChange.java
@@ -26,9 +26,11 @@ import com.ning.billing.catalog.api.PhaseType;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PlanSpecifier;
 import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
-public abstract class CaseChange<T>  extends ValidatingConfig {
+public abstract class CaseChange<T>  extends ValidatingConfig<Catalog> {
 
 	@XmlElement(required=false)
 	private PhaseType phaseType;
diff --git a/catalog/src/main/java/com/ning/billing/catalog/CasePhase.java b/catalog/src/main/java/com/ning/billing/catalog/CasePhase.java
index 36cafc3..5941802 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/CasePhase.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/CasePhase.java
@@ -23,6 +23,7 @@ import com.ning.billing.catalog.api.PhaseType;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PlanSpecifier;
 import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.util.config.ValidationErrors;
 
 public abstract class CasePhase<T> extends Case<T> {
 
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 d96aee8..684c131 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Catalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Catalog.java
@@ -16,7 +16,7 @@
 
 package com.ning.billing.catalog;
 
-import java.net.URL;
+import java.util.Collection;
 import java.util.Date;
 
 import javax.xml.bind.annotation.XmlAccessType;
@@ -35,18 +35,21 @@ import com.ning.billing.catalog.api.PlanAlignmentChange;
 import com.ning.billing.catalog.api.PlanAlignmentCreate;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationError;
+import com.ning.billing.util.config.ValidationErrors;
 
 @XmlRootElement
 @XmlAccessorType(XmlAccessType.NONE)
-public class Catalog extends ValidatingConfig implements ICatalog {
-	public PlanRules getPlanRules() {
+public class Catalog extends ValidatingConfig<Catalog> implements ICatalog {
+	public PlanRules getPlanRules() { 
 		return planRules;
 	}
 
 	public void setPlanRules(PlanRules planRules) {
 		this.planRules = planRules;
 	}
-
+ 
 	@XmlElement(required=true)
 	private Date effectiveDate;
 
@@ -185,14 +188,22 @@ public class Catalog extends ValidatingConfig implements ICatalog {
 
 	@Override
 	public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
-		errors.addAll(validate(catalog,errors, products));
-		errors.addAll(validate(catalog,errors, priceLists));
-		errors.addAll(validate(catalog,errors, plans));
-		errors.addAll(planRules.validate(catalog, errors));
+		validate(catalog,errors, products);
+		validate(catalog,errors, priceLists);
+		validate(catalog,errors, plans);
+		planRules.validate(catalog, errors);
 		return errors;
 	}
 
-    @Override
+    private Collection<? extends ValidationError> validate(Catalog catalog,
+			ValidationErrors errors, ValidatingConfig<Catalog>[] configs) {
+		for(ValidatingConfig<Catalog> config: configs) {
+			
+		}
+		return null;
+	}
+
+	@Override
     public ActionPolicy getPlanChangePolicy(PlanPhaseSpecifier from, PlanSpecifier to) {
         return planRules.getPlanChangePolicy(from, to, this);
     }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/CatalogService.java b/catalog/src/main/java/com/ning/billing/catalog/CatalogService.java
index 8e91594..6f04aa6 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/CatalogService.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/CatalogService.java
@@ -16,21 +16,16 @@
 
 package com.ning.billing.catalog;
 
-import java.io.File;
-import java.net.URI;
-
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.ning.billing.catalog.api.ICatalog;
 import com.ning.billing.catalog.api.ICatalogService;
-import com.ning.billing.catalog.io.CatalogLoader;
 import com.ning.billing.config.ICatalogConfig;
 import com.ning.billing.lifecycle.IService;
-
+import com.ning.billing.util.config.XMLLoader;
 
 public class CatalogService implements IService, Provider<ICatalog>, ICatalogService {
 
-
     private static final String CATALOG_SERVICE_NAME = "catalog-service";
 
     private static ICatalog catalog;
@@ -50,7 +45,7 @@ public class CatalogService implements IService, Provider<ICatalog>, ICatalogSer
     public synchronized void initialize() throws ServiceException {
         if (!isInitialized) {
             try {
-                catalog = CatalogLoader.getCatalogFromProperty(config.getCatalogURI());
+                catalog = XMLLoader.getObjectFromProperty(config.getCatalogURI(), Catalog.class);
                 isInitialized = true;
             } catch (Exception e) {
                 throw new ServiceException(e);
@@ -58,7 +53,6 @@ public class CatalogService implements IService, Provider<ICatalog>, ICatalogSer
         }
     }
 
-    @Override
     public String getName() {
         return CATALOG_SERVICE_NAME;
     }
diff --git a/catalog/src/main/java/com/ning/billing/catalog/CatalogUserApi.java b/catalog/src/main/java/com/ning/billing/catalog/CatalogUserApi.java
index a2ff0b0..b42d12b 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/CatalogUserApi.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/CatalogUserApi.java
@@ -20,7 +20,7 @@ import java.io.File;
 
 import com.ning.billing.catalog.api.ICatalog;
 import com.ning.billing.catalog.api.ICatalogUserApi;
-import com.ning.billing.catalog.io.CatalogLoader;
+import com.ning.billing.util.config.XMLLoader;
 
 public class CatalogUserApi implements ICatalogUserApi {
 
@@ -28,7 +28,7 @@ public class CatalogUserApi implements ICatalogUserApi {
     public ICatalog getCatalog(final String catalogName) {
     	String name = catalogName;
         try {
-            return CatalogLoader.getCatalogFromURI(new File(name).toURI());
+            return XMLLoader.getObjectFromURI(new File(name).toURI(), Catalog.class);
         } catch (Exception e) {
             e.printStackTrace();
             return null;
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 5e7909a..ac34cf6 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Duration.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Duration.java
@@ -22,9 +22,11 @@ import javax.xml.bind.annotation.XmlElement;
 
 import com.ning.billing.catalog.api.IDuration;
 import com.ning.billing.catalog.api.TimeUnit;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
-public class Duration extends ValidatingConfig implements IDuration {
+public class Duration extends ValidatingConfig<Catalog> implements IDuration {
 	@XmlElement(required=true)
     private TimeUnit unit;
 
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 48d9782..0917266 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/InternationalPrice.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/InternationalPrice.java
@@ -26,9 +26,11 @@ import javax.xml.bind.annotation.XmlElement;
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.catalog.api.IInternationalPrice;
 import com.ning.billing.catalog.api.IPrice;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
-public class InternationalPrice extends ValidatingConfig implements IInternationalPrice {
+public class InternationalPrice extends ValidatingConfig<Catalog> implements IInternationalPrice {
 
 	//TODO MDW Validation - effectiveDateForExistingSubscriptons > catalog effectiveDate 
 	@XmlElement(required=false)
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 25acae4..9bc2314 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
@@ -19,6 +19,7 @@ package com.ning.billing.catalog.io;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.MalformedURLException;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.util.ArrayList;
@@ -33,23 +34,23 @@ import org.xml.sax.SAXException;
 import com.ning.billing.catalog.Catalog;
 import com.ning.billing.catalog.VersionedCatalog;
 import com.ning.billing.catalog.api.InvalidConfigException;
+import com.ning.billing.util.config.XMLLoader;
 
-public class VersionedCatalogLoader implements ICatalogLoader {
+public class VersionedCatalogLoader  {
 	private  final String XML_EXTENSION = ".xml";
 	private  final String HREF_LOW_START = "href=\""; 
 	private  final String HREF_CAPS_START = "HREF=\""; 
 	private  final String HREF_SEARCH_END = "\"";
-		
+			
 	/* (non-Javadoc)
 	 * @see com.ning.billing.catalog.io.ICatalogLoader#load(java.net.URL)
 	 */
-	@Override
-	public  VersionedCatalog load(URL url) throws IOException, SAXException, InvalidConfigException, JAXBException, TransformerException {
+	public  VersionedCatalog load(URL url) throws IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException {
 		String directoryContents = pullContentsFrom(url);
 		List<URL> xmlURLs = findXmlReferences(directoryContents, url);
 		VersionedCatalog result = new VersionedCatalog();
 		for(URL u : xmlURLs) {
-			Catalog catalog = CatalogLoader.getCatalogFromURL(u);
+			Catalog catalog = XMLLoader.getObjectFromURL(u, Catalog.class);
 			result.add(catalog);
 		}
 		return result;
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 bfdd093..a0244b7 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Plan.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Plan.java
@@ -31,9 +31,11 @@ import com.ning.billing.catalog.api.BillingPeriod;
 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.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
-public class Plan extends ValidatingConfig implements IPlan {
+public class Plan extends ValidatingConfig<Catalog> implements IPlan {
 
 
 	@XmlAttribute(required=true)
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 b1367c0..36250b4 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PlanPhase.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PlanPhase.java
@@ -27,9 +27,11 @@ import com.ning.billing.catalog.api.IInternationalPrice;
 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.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
-public class PlanPhase extends ValidatingConfig implements IPlanPhase {
+public class PlanPhase extends ValidatingConfig<Catalog> implements IPlanPhase {
 
 	@XmlAttribute (required=true)
 	private PhaseType type;
diff --git a/catalog/src/main/java/com/ning/billing/catalog/PlanPolicyChangeRule.java b/catalog/src/main/java/com/ning/billing/catalog/PlanPolicyChangeRule.java
index 816c1f6..8b8079b 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PlanPolicyChangeRule.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PlanPolicyChangeRule.java
@@ -22,9 +22,11 @@ import javax.xml.bind.annotation.XmlElement;
 
 import com.ning.billing.catalog.api.ActionPolicy;
 import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
-public class PlanPolicyChangeRule extends ValidatingConfig {
+public class PlanPolicyChangeRule extends ValidatingConfig<Catalog> {
 	public enum Qualifier {
 		DEFAULT,
 		PRODUCT_FROM_LOW_TO_HIGH,
diff --git a/catalog/src/main/java/com/ning/billing/catalog/PlanRules.java b/catalog/src/main/java/com/ning/billing/catalog/PlanRules.java
index fa36049..e2ff36d 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PlanRules.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PlanRules.java
@@ -29,9 +29,11 @@ import com.ning.billing.catalog.api.PlanAlignmentChange;
 import com.ning.billing.catalog.api.PlanAlignmentCreate;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
-public class PlanRules extends ValidatingConfig  {
+public class PlanRules extends ValidatingConfig<Catalog>  {
 
 	@XmlElementWrapper(name="tiers", required=true)
 	@XmlElement(name="tier", required=false) // may not have tiers in some catalogs
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 9dcbcba..885191e 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Price.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Price.java
@@ -24,9 +24,11 @@ import javax.xml.bind.annotation.XmlElement;
 
 import com.ning.billing.catalog.api.Currency;
 import com.ning.billing.catalog.api.IPrice;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
-public class Price extends ValidatingConfig implements IPrice {
+public class Price extends ValidatingConfig<Catalog> implements IPrice {
 	@XmlElement(required=true)
 	private Currency currency;
 
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 76e55bb..2cc5cd1 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PriceList.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PriceList.java
@@ -25,9 +25,11 @@ import javax.xml.bind.annotation.XmlID;
 import javax.xml.bind.annotation.XmlIDREF;
 
 import com.ning.billing.catalog.api.IPriceList;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
-public class PriceList extends ValidatingConfig implements IPriceList {
+public class PriceList extends ValidatingConfig<Catalog> implements IPriceList {
 
 	@XmlAttribute(required=true)
 	@XmlID
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 310837c..48924d1 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Product.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Product.java
@@ -26,9 +26,11 @@ import javax.xml.bind.annotation.XmlIDREF;
 
 import com.ning.billing.catalog.api.IProduct;
 import com.ning.billing.catalog.api.ProductCategory;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
 
 @XmlAccessorType(XmlAccessType.NONE)
-public class Product extends ValidatingConfig implements IProduct {
+public class Product extends ValidatingConfig<Catalog> implements IProduct {
 	
 	@XmlAttribute (required=true)
 	@XmlID
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 055ccd7..f8eed4f 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
@@ -33,8 +33,10 @@ import com.ning.billing.catalog.api.PlanAlignmentChange;
 import com.ning.billing.catalog.api.PlanAlignmentCreate;
 import com.ning.billing.catalog.api.PlanPhaseSpecifier;
 import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.util.config.ValidatingConfig;
+import com.ning.billing.util.config.ValidationErrors;
 
-public class VersionedCatalog extends ValidatingConfig implements ICatalog {
+public class VersionedCatalog extends ValidatingConfig<Catalog> implements ICatalog {
 	
 	private Catalog currentCatalog;
 	
@@ -140,7 +142,7 @@ public class VersionedCatalog extends ValidatingConfig implements ICatalog {
 	@Override
 	public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
 		for(Catalog c : versions) {
-			errors.addAll(c.validate());
+			errors.addAll(c.validate(c, errors));
 		}
 		return errors;
 	}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java b/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java
index e858b82..0035bc8 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java
@@ -20,6 +20,7 @@ import static org.testng.AssertJUnit.assertTrue;
 
 import java.io.IOException;
 import java.net.MalformedURLException;
+import java.net.URISyntaxException;
 import java.net.URL;
 import java.util.Iterator;
 import java.util.List;
@@ -126,7 +127,7 @@ public class TestVersionedCatalogLoader {
 	}
 	
 	@Test(enabled=true)
-	public void testLoad() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException {
+	public void testLoad() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException {
 		VersionedCatalog c = loader.load(Resources.getResource("versionedCatalog"));
 		assertEquals(4, c.size());
 		Iterator<Catalog> it = c.iterator();
diff --git a/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java b/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java
index b0d1690..b856849 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java
@@ -17,6 +17,7 @@
 package com.ning.billing.catalog.io;
 
 import java.io.IOException;
+import java.net.URISyntaxException;
 
 import javax.xml.bind.JAXBException;
 import javax.xml.transform.TransformerException;
@@ -25,14 +26,16 @@ import org.testng.annotations.Test;
 import org.xml.sax.SAXException;
 
 import com.google.common.io.Resources;
+import com.ning.billing.catalog.Catalog;
 import com.ning.billing.catalog.api.InvalidConfigException;
+import com.ning.billing.util.config.XMLLoader;
 
 public class TestXMLReader {
 
 	@Test(enabled=true)
-	public void testCatalogLoad() throws IOException, TransformerException, JAXBException, SAXException, InvalidConfigException {
-		CatalogLoader.getCatalogFromURL(Resources.getResource("WeaponsHire.xml"));
-		CatalogLoader.getCatalogFromURL(Resources.getResource("WeaponsHireSmall.xml"));
+	public void testCatalogLoad() throws IOException, TransformerException, JAXBException, SAXException, InvalidConfigException, URISyntaxException {
+		XMLLoader.getObjectFromURL(Resources.getResource("WeaponsHire.xml"), Catalog.class);
+		XMLLoader.getObjectFromURL(Resources.getResource("WeaponsHireSmall.xml"), Catalog.class);
 	}
 	
 }
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java b/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
index ee4d094..4515af1 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
@@ -19,6 +19,7 @@ import static org.testng.AssertJUnit.assertEquals;
 
 import java.io.IOException;
 import java.net.MalformedURLException;
+import java.net.URISyntaxException;
 import java.util.Date;
 
 import javax.xml.bind.JAXBException;
@@ -30,21 +31,20 @@ import org.xml.sax.SAXException;
 
 import com.google.common.io.Resources;
 import com.ning.billing.catalog.api.InvalidConfigException;
-import com.ning.billing.catalog.io.ICatalogLoader;
 import com.ning.billing.catalog.io.VersionedCatalogLoader;
 
 public class TestVersionedCatalog {
-	private final ICatalogLoader loader = new VersionedCatalogLoader();
+	private final VersionedCatalogLoader loader = new VersionedCatalogLoader();
 
 	@Test(enabled=true)
-	public void testAddCatalog() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException {
+	public void testAddCatalog() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException {
 		VersionedCatalog vc = loader.load(Resources.getResource("versionedCatalog"));
 		vc.add(new Catalog(new Date()));
 		assertEquals(5, vc.size());
 	}
 	
 	@Test(enabled=true)
-	public void testApplyEffectiveDate() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException {
+	public void testApplyEffectiveDate() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException, TransformerException, URISyntaxException {
 		VersionedCatalog vc = loader.load(Resources.getResource("versionedCatalog"));
 		Date d = new Date(1L);
 		vc.configureEffectiveDate(d);

invoice/pom.xml 5(+4 -1)

diff --git a/invoice/pom.xml b/invoice/pom.xml
index 8addd0a..e29e10a 100644
--- a/invoice/pom.xml
+++ b/invoice/pom.xml
@@ -23,7 +23,10 @@
         <dependency>
             <groupId>com.ning.billing</groupId>
             <artifactId>killbill-api</artifactId>
-            <version>0.0.7-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.ning.billing</groupId>
+            <artifactId>killbill-util</artifactId>
         </dependency>
         <dependency>
             <groupId>org.testng</groupId>
diff --git a/util/src/main/java/com/ning/billing/util/config/ValidatingConfig.java b/util/src/main/java/com/ning/billing/util/config/ValidatingConfig.java
new file mode 100644
index 0000000..5c2b87a
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/config/ValidatingConfig.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.util.config;
+
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+
+@XmlAccessorType(XmlAccessType.NONE)
+public abstract class ValidatingConfig<Context> {
+	/**
+	 * All must implement validation
+	 * 
+	 * @param root
+	 * @param errors
+	 * @return
+	 */
+	public abstract ValidationErrors validate(Context root, ValidationErrors errors);
+	
+	
+	/**
+	 * Override  to initialize
+	 * 
+	 * @param root
+	 */
+	public void initialize(Context root){} 
+	
+
+}
diff --git a/util/src/main/java/com/ning/billing/util/config/XMLSchemaGenerator.java b/util/src/main/java/com/ning/billing/util/config/XMLSchemaGenerator.java
new file mode 100644
index 0000000..178529a
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/config/XMLSchemaGenerator.java
@@ -0,0 +1,105 @@
+/*
+ * 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.util.config;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.SchemaOutputResolver;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Result;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.w3c.dom.Document;
+
+public class XMLSchemaGenerator {
+	final private static  int MAX_SCHEMA_SIZE_IN_BYTES = 100000;
+
+
+	//Note: this main method is called by the maven build to generate the schema for the jar
+	public static void main(String[] args) throws IOException, TransformerException, JAXBException, ClassNotFoundException {
+		if (args.length != 2) {
+			printUsage();
+			System.exit(0);
+		}
+		Class<?> clazz = (Class<?>)args.getClass().getClassLoader().loadClass(args[1]);
+		
+		JAXBContext context =JAXBContext.newInstance(clazz);
+		String xsdFileName = "Schema.xsd";
+		if(args.length != 0) {
+			xsdFileName = args[0] + "/" + xsdFileName;
+		}
+		FileOutputStream s = new FileOutputStream(xsdFileName);
+		pojoToXSD(context, s);
+	}
+
+	private static void printUsage() {
+		System.out.println(XMLSchemaGenerator.class.getName() + " <file> <class1>");
+		
+	}
+
+	public static StreamSource xmlSchema(Class<?> clazz) throws IOException, TransformerException, JAXBException {
+		ByteArrayOutputStream output = new ByteArrayOutputStream(MAX_SCHEMA_SIZE_IN_BYTES);
+		JAXBContext context =JAXBContext.newInstance(clazz);
+		pojoToXSD(context, output);
+		StreamSource source = new StreamSource(new ByteArrayInputStream(output.toByteArray()));
+		return source;
+	}
+
+	public static void pojoToXSD(JAXBContext context, OutputStream out)
+		    throws IOException, TransformerException
+		{
+		    final List<DOMResult> results = new ArrayList<DOMResult>();
+
+		    context.generateSchema(new SchemaOutputResolver() {
+		        @Override
+		        public Result createOutput(String ns, String file)
+		                throws IOException {
+		            DOMResult result = new DOMResult();
+		            result.setSystemId(file);
+		            results.add(result);
+		            return result;
+		        }
+		    });
+
+		    DOMResult domResult = results.get(0);
+		    Document doc = (Document) domResult.getNode();
+
+		    // Use a Transformer for output
+		    TransformerFactory tFactory = TransformerFactory.newInstance();
+		    Transformer transformer = tFactory.newTransformer();
+
+		    DOMSource source = new DOMSource(doc);
+		    StreamResult result = new StreamResult(out);
+		    transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+		    transformer.transform(source, result);
+		}
+
+}