Details
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 2ce3ef9..0c9940d 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PriceList.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PriceList.java
@@ -28,6 +28,7 @@ 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.ValidationError;
import com.ning.billing.util.config.ValidationErrors;
@XmlAccessorType(XmlAccessType.NONE)
@@ -76,9 +77,29 @@ public class PriceList extends ValidatingConfig<Catalog> implements IPriceList
}
@Override
- public ValidationErrors validate(Catalog root, ValidationErrors errors) {
+ public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
+ for (Plan cur : getPlans()) {
+ int numPlans = findNumberOfPlans(cur.getProduct(), cur.getBillingPeriod());
+ if ( numPlans > 1 ) {
+ errors.add(new ValidationError(
+ String.format("There are %d plans in pricelist %s and have the same product/billingPeriod (%s, %s)",
+ numPlans, getName(), cur.getProduct(), cur.getBillingPeriod()), catalog.getCatalogURI(),
+ PriceListSet.class, getName()));
+ }
+ }
return errors;
}
+
+ private int findNumberOfPlans(IProduct product, BillingPeriod period) {
+ int count = 0;
+ for (Plan cur : getPlans()) {
+ if (cur.getProduct().equals(product) &&
+ (cur.getBillingPeriod() == null || cur.getBillingPeriod().equals(period))) {
+ count++;
+ }
+ }
+ return count;
+ }
}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java b/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java
index 781f44d..2bd9310 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PriceListDefault.java
@@ -34,7 +34,8 @@ public class PriceListDefault extends PriceList {
@Override
public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
- if(getName().equals(IPriceListSet.DEFAULT_PRICELIST_NAME)) {
+ super.validate(catalog, errors);
+ if(!getName().equals(IPriceListSet.DEFAULT_PRICELIST_NAME)) {
errors.add(new ValidationError("The name of the default pricelist must be 'DEFAULT'",
catalog.getCatalogURI(), PriceList.class, getName()));
diff --git a/catalog/src/main/java/com/ning/billing/catalog/PriceListSet.java b/catalog/src/main/java/com/ning/billing/catalog/PriceListSet.java
index 10010a7..fbda299 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PriceListSet.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PriceListSet.java
@@ -73,12 +73,15 @@ public class PriceListSet extends ValidatingConfig<Catalog> {
}
@Override
- public ValidationErrors validate(Catalog root, ValidationErrors errors) {
+ public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
+ defaultPricelist.validate(catalog, errors);
//Check that the default pricelist name is not in use in the children
for(PriceList pl : childPriceLists) {
if(pl.getName().equals(IPriceListSet.DEFAULT_PRICELIST_NAME)){
- errors.add(new ValidationError("Pricelists cannot use the reserved name '" + IPriceListSet.DEFAULT_PRICELIST_NAME + "'", root.getCatalogURI(), PriceListSet.class, pl.getName()));
+ errors.add(new ValidationError("Pricelists cannot use the reserved name '" + IPriceListSet.DEFAULT_PRICELIST_NAME + "'",
+ catalog.getCatalogURI(), PriceListSet.class, pl.getName()));
}
+ pl.validate(catalog, errors); // and validate the individual pricelists
}
return errors;
}
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 4a68dac..33af867 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
@@ -49,4 +49,8 @@ public class ValidationError {
public void log(Logger log) {
log.error(String.format("%s [%s] (%s:%s)", description, sourceURI, objectType, objectName));
}
+
+ public String toString() {
+ return String.format("%s [%s] (%s:%s)\n", 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 901f636..19e4270 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
@@ -35,5 +35,13 @@ public class ValidationErrors extends ArrayList<ValidationError>{
error.log(log);
}
}
+
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ for(ValidationError error : this) {
+ builder.append(error.toString());
+ }
+ return builder.toString();
+ }
}
\ No newline at end of file
diff --git a/util/src/main/java/com/ning/billing/util/config/ValidationException.java b/util/src/main/java/com/ning/billing/util/config/ValidationException.java
new file mode 100644
index 0000000..cd5c9c1
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/config/ValidationException.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.util.config;
+
+import java.io.PrintStream;
+
+public class ValidationException extends Exception {
+ private final ValidationErrors errors;
+
+ ValidationException(ValidationErrors errors) {
+ this.errors = errors;
+ }
+
+ public ValidationErrors getErrors() {
+ return errors;
+ }
+
+ @Override
+ public void printStackTrace(PrintStream arg0) {
+ arg0.print(errors.toString());
+ super.printStackTrace(arg0);
+ }
+
+
+}
+
diff --git a/util/src/main/java/com/ning/billing/util/config/XMLLoader.java b/util/src/main/java/com/ning/billing/util/config/XMLLoader.java
index 481447c..9ed3bce 100644
--- a/util/src/main/java/com/ning/billing/util/config/XMLLoader.java
+++ b/util/src/main/java/com/ning/billing/util/config/XMLLoader.java
@@ -56,22 +56,31 @@ public class XMLLoader {
return getObjectFromStream(uri, UriAccessor.accessUri(uri), objectType);
}
- public static <T extends ValidatingConfig<T>> T getObjectFromStream(URI uri, InputStream stream, Class<T> clazz) throws SAXException, InvalidConfigException, JAXBException, IOException, TransformerException {
+ public static <T extends ValidatingConfig<T>> T getObjectFromStream(URI uri, InputStream stream, Class<T> clazz) throws SAXException, InvalidConfigException, JAXBException, IOException, TransformerException, ValidationException {
Object o = unmarshaller(clazz).unmarshal(stream);
if (clazz.isInstance(o)) {
@SuppressWarnings("unchecked")
T castObject = (T)o;
- validate(uri,castObject);
+ try {
+ validate(uri,castObject);
+ } catch (ValidationException e) {
+ e.getErrors().log(log);
+ System.err.println(e.getErrors().toString());
+ throw e;
+ }
return castObject;
} else {
return null;
}
}
- public static <T extends ValidatingConfig<T>> void validate(URI uri, T c) {
+ public static <T extends ValidatingConfig<T>> void validate(URI uri, T c) throws ValidationException {
c.initialize(c, uri);
ValidationErrors errs = c.validate(c, new ValidationErrors());
- log.info("Errors: " + errs.size() + " for " + uri);
+ log.info("Errors: " + errs.size() + " for " + uri);
+ if(errs.size() > 0) {
+ throw new ValidationException(errs);
+ }
}
public static Unmarshaller unmarshaller(Class<?> clazz) throws JAXBException, SAXException, IOException, TransformerException {
diff --git a/util/src/test/java/com/ning/billing/util/config/TestXMLLoader.java b/util/src/test/java/com/ning/billing/util/config/TestXMLLoader.java
index 02fbcd2..30b8ee3 100644
--- a/util/src/test/java/com/ning/billing/util/config/TestXMLLoader.java
+++ b/util/src/test/java/com/ning/billing/util/config/TestXMLLoader.java
@@ -44,7 +44,7 @@ public class TestXMLLoader {
"</xmlTestClass>";
@Test
- public void test() throws SAXException, InvalidConfigException, JAXBException, IOException, TransformerException, URISyntaxException {
+ public void test() throws SAXException, InvalidConfigException, JAXBException, IOException, TransformerException, URISyntaxException, ValidationException {
InputStream is = new ByteArrayInputStream(TEST_XML.getBytes());
XmlTestClass test = XMLLoader.getObjectFromStream(new URI("internal:/"), is, XmlTestClass.class);
assertEquals(test.getFoo(), "foo");