killbill-memoizeit

catalog: Add catalog validation at the time we upload catalog

1/10/2017 9:34:05 PM

Details

diff --git a/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java b/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java
index 48e22ad..048f41c 100644
--- a/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java
+++ b/catalog/src/main/java/org/killbill/billing/catalog/api/user/DefaultCatalogUserApi.java
@@ -94,25 +94,38 @@ public class  DefaultCatalogUserApi implements CatalogUserApi {
         final InternalTenantContext internalTenantContext = createInternalTenantContext(callContext);
         try {
 
-            final StaticCatalog currentCatalog = catalogService.getCurrentCatalog(false, true, internalTenantContext);
-
+            final VersionedCatalog versionedCatalog = (VersionedCatalog) catalogService.getFullCatalog(false, true, internalTenantContext);
 
             // Validation purpose:  Will throw if bad XML or catalog validation fails
             final InputStream stream = new ByteArrayInputStream(catalogXML.getBytes());
             final StaticCatalog newCatalogVersion = XMLLoader.getObjectFromStream(new URI("dummy"), stream, StandaloneCatalog.class);
 
-            // currentCatalog.getCatalogName() could be null if tenant was created with a default catalog
-            if (currentCatalog != null && currentCatalog.getCatalogName() !=  null) {
-                if (!newCatalogVersion.getCatalogName().equals(currentCatalog.getCatalogName())) {
+            if (versionedCatalog != null) {
+
+                // currentCatalog.getCatalogName() could be null if tenant was created with a default catalog
+                if (versionedCatalog.getCatalogName() !=  null && !newCatalogVersion.getCatalogName().equals(versionedCatalog.getCatalogName())) {
                     final ValidationErrors errors = new ValidationErrors();
-                    errors.add(String.format("Catalog name '%s' should match previous catalog name '%s'", newCatalogVersion.getCatalogName(), currentCatalog.getCatalogName()),
-                                                   new URI("dummy"), StandaloneCatalog.class, "");
+                    errors.add(String.format("Catalog name '%s' should match previous catalog name '%s'", newCatalogVersion.getCatalogName(), versionedCatalog.getCatalogName()),
+                               new URI("dummy"), StandaloneCatalog.class, "");
                     // Bummer ValidationException CTOR is private to package...
                     //final ValidationException validationException = new ValidationException(errors);
                     //throw new CatalogApiException(errors, ErrorCode.CAT_INVALID_FOR_TENANT, internalTenantContext.getTenantRecordId());
                     logger.info("Failed to load new catalog version: " + errors.toString());
                     throw new CatalogApiException(ErrorCode.CAT_INVALID_FOR_TENANT, internalTenantContext.getTenantRecordId());
                 }
+
+                for (StandaloneCatalog c : versionedCatalog.getVersions()) {
+                    if (c.getEffectiveDate().compareTo(newCatalogVersion.getEffectiveDate()) == 0) {
+                        final ValidationErrors errors = new ValidationErrors();
+                        errors.add(String.format("Catalog version for effectiveDate '%s' already exists", newCatalogVersion.getEffectiveDate()),
+                                   new URI("dummy"), StandaloneCatalog.class, "");
+                        // Bummer ValidationException CTOR is private to package...
+                        //final ValidationException validationException = new ValidationException(errors);
+                        //throw new CatalogApiException(errors, ErrorCode.CAT_INVALID_FOR_TENANT, internalTenantContext.getTenantRecordId());
+                        logger.info("Failed to load new catalog version: " + errors.toString());
+                        throw new CatalogApiException(ErrorCode.CAT_INVALID_FOR_TENANT, internalTenantContext.getTenantRecordId());
+                    }
+                }
             }
 
             catalogCache.clearCatalog(internalTenantContext);
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCatalog.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCatalog.java
index 25fc129..d7ab1b3 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCatalog.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestCatalog.java
@@ -26,9 +26,8 @@ import java.util.Set;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
-import org.killbill.billing.catalog.StandaloneCatalog;
-import org.killbill.billing.catalog.VersionedCatalog;
 import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.CatalogApiException;
 import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.catalog.api.ProductCategory;
 import org.killbill.billing.catalog.api.TimeUnit;
@@ -41,7 +40,6 @@ import org.killbill.billing.client.model.Product;
 import org.killbill.billing.client.model.SimplePlan;
 import org.killbill.billing.client.model.Tenant;
 import org.killbill.billing.client.model.Usage;
-import org.killbill.xmlloader.XMLLoader;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -62,6 +60,32 @@ public class TestCatalog extends TestJaxrsBase {
         //
     }
 
+    @Test(groups = "slow")
+    public void testUploadWithErrors() throws Exception {
+        final String versionPath1 = Resources.getResource("SpyCarBasic.xml").getPath();
+        killBillClient.uploadXMLCatalog(versionPath1, requestOptions);
+
+        // Retry to upload same version
+        try {
+            killBillClient.uploadXMLCatalog(versionPath1, requestOptions);
+            Assert.fail("Uploading same version should fail");
+        } catch (KillBillClientException e) {
+            Assert.assertEquals(e.getMessage(), "Invalid catalog for tenant : 1");
+        }
+
+        // Try to upload another version with an invalid name (different than orignal name)
+        try {
+            final String versionPath2 = Resources.getResource("SpyCarBasicInvalidName.xml").getPath();
+            killBillClient.uploadXMLCatalog(versionPath2, requestOptions);
+            Assert.fail("Uploading same version should fail");
+        } catch (KillBillClientException e) {
+            Assert.assertEquals(e.getMessage(), "Invalid catalog for tenant : 1");
+        }
+
+        String catalog = killBillClient.getXMLCatalog(requestOptions);
+        Assert.assertNotNull(catalog);
+    }
+
     @Test(groups = "slow", description = "Can retrieve a json version of the catalog")
     public void testCatalog() throws Exception {
         final Set<String> allBasePlans = new HashSet<String>();