killbill-uncached
Changes
account/pom.xml 104(+75 -29)
account/src/main/resources/ddl.sql 10(+10 -0)
account/src/test/resources/log4j.xml 36(+36 -0)
analytics/pom.xml 2(+1 -1)
api/pom.xml 5(+5 -0)
catalog/src/test/resources/WeaponsHire.xml 96(+40 -56)
catalog/src/test/resources/WeaponsHireSmall.xml 39(+15 -24)
entitlement/src/main/java/com/ning/billing/entitlement/alignment/EntitlementAlignment.java 148(+0 -148)
entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java 6(+3 -3)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java 11(+4 -7)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java 20(+4 -16)
entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java 10(+6 -4)
entitlement/src/test/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorMemoryMock.java 4(+2 -2)
entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoMemoryMock.java 6(+3 -3)
entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoSqlMock.java 4(+2 -2)
entitlement/src/test/resources/testInput.xml 106(+43 -63)
pom.xml 4(+2 -2)
Details
account/pom.xml 104(+75 -29)
diff --git a/account/pom.xml b/account/pom.xml
index fda1f24..a899a89 100644
--- a/account/pom.xml
+++ b/account/pom.xml
@@ -1,33 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!--
- ~ 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.
- -->
+<!-- ~ 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. -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>com.ning.billing</groupId>
- <artifactId>killbill</artifactId>
- <version>0.0.3-SNAPSHOT</version>
- <relativePath>../pom.xml</relativePath>
- </parent>
- <artifactId>killbill-account</artifactId>
- <name>killbill-account</name>
- <packaging>jar</packaging>
- <dependencies>
- </dependencies>
- <build>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill</artifactId>
+ <version>0.0.3-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+ <artifactId>killbill-account</artifactId>
+ <name>killbill-account</name>
+ <packaging>jar</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.jdbi</groupId>
+ <artifactId>jdbi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.inject</groupId>
+ <artifactId>guice</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ning.billing</groupId>
+ <artifactId>killbill-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.skife.config</groupId>
+ <artifactId>config-magic</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <groups>setup,fast</groups>
+ </configuration>
+ </plugin>
+ </plugins>
</build>
</project>
diff --git a/account/src/main/java/com/ning/billing/account/api/Account.java b/account/src/main/java/com/ning/billing/account/api/Account.java
new file mode 100644
index 0000000..283f141
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/api/Account.java
@@ -0,0 +1,83 @@
+/*
+ * 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.account.api;
+
+import java.util.UUID;
+
+import com.ning.billing.catalog.api.Currency;
+
+public class Account implements IAccount {
+
+ private final UUID id;
+ private final String key;
+
+ public Account(String key) {
+ this(UUID.randomUUID(), key);
+ }
+
+
+ public Account(UUID id, String key) {
+ super();
+ this.id = id;
+ this.key = key;
+ }
+
+ @Override
+ public UUID getId() {
+ return id;
+ }
+
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ @Override
+ public String getName() {
+ return null;
+ }
+
+ @Override
+ public String getEmail() {
+ return null;
+ }
+
+ @Override
+ public String getPhone() {
+ return null;
+ }
+
+
+ @Override
+ public int getBillCycleDay() {
+ return 0;
+ }
+
+ @Override
+ public Currency getCurrency() {
+ return null;
+ }
+
+ @Override
+ public void setPrivate(String name, String value) {
+ }
+
+ @Override
+ public String getPrivate(String name) {
+ return null;
+ }
+}
diff --git a/account/src/main/java/com/ning/billing/account/dao/IAccountDao.java b/account/src/main/java/com/ning/billing/account/dao/IAccountDao.java
new file mode 100644
index 0000000..ed9693e
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/dao/IAccountDao.java
@@ -0,0 +1,34 @@
+/*
+ * 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.account.dao;
+
+import java.util.List;
+import java.util.UUID;
+
+import com.ning.billing.account.api.IAccount;
+
+public interface IAccountDao {
+
+ public void createAccount(IAccount account);
+
+ public IAccount getAccountByKey(String key);
+
+ public IAccount getAccountFromId(UUID uid);
+
+ public List<IAccount> getAccounts();
+
+}
diff --git a/account/src/main/java/com/ning/billing/account/dao/IAccountDaoSql.java b/account/src/main/java/com/ning/billing/account/dao/IAccountDaoSql.java
new file mode 100644
index 0000000..c7068c1
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/dao/IAccountDaoSql.java
@@ -0,0 +1,76 @@
+/*
+ * 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.account.dao;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.UUID;
+
+import org.skife.jdbi.v2.SQLStatement;
+import org.skife.jdbi.v2.StatementContext;
+import org.skife.jdbi.v2.sqlobject.Bind;
+import org.skife.jdbi.v2.sqlobject.Binder;
+import org.skife.jdbi.v2.sqlobject.SqlQuery;
+import org.skife.jdbi.v2.sqlobject.SqlUpdate;
+import org.skife.jdbi.v2.sqlobject.customizers.Mapper;
+import org.skife.jdbi.v2.sqlobject.mixins.CloseMe;
+import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
+import org.skife.jdbi.v2.tweak.ResultSetMapper;
+
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.IAccount;
+
+
+public interface IAccountDaoSql extends Transactional<IAccountDaoSql>, CloseMe {
+
+ @SqlUpdate("insert into accounts (id, key_name) values (:id, :key_name)")
+ public void insertAccount(@Bind(binder = IAccountSqlBinder.class) IAccount account);
+
+ @SqlQuery("select id, key_name from accounts where key_name = :key_name")
+ @Mapper(IAccountSqlMapper.class)
+ public IAccount getAccountByKey(@Bind("key_name") String key);
+
+ @SqlQuery("select id, key_name from accounts where id = :id")
+ @Mapper(IAccountSqlMapper.class)
+ public IAccount getAccountFromId(@Bind("id") String id);
+
+ @SqlQuery("select id, key_name from accounts")
+ @Mapper(IAccountSqlMapper.class)
+ public List<IAccount> getAccounts();
+
+
+ public static class IAccountSqlBinder implements Binder<Bind, IAccount> {
+
+ @Override
+ public void bind(@SuppressWarnings("rawtypes") SQLStatement stmt, Bind bind, IAccount account) {
+ stmt.bind("id", account.getId().toString());
+ stmt.bind("key_name", account.getKey());
+ }
+ }
+
+ public static class IAccountSqlMapper implements ResultSetMapper<IAccount> {
+
+ @Override
+ public IAccount map(int index, ResultSet r, StatementContext ctx)
+ throws SQLException {
+ UUID id = UUID.fromString(r.getString("id"));
+ String key = r.getString("key_name");
+ return new Account(id, key);
+ }
+ }
+}
diff --git a/account/src/main/java/com/ning/billing/account/glue/AccountModule.java b/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
new file mode 100644
index 0000000..cf917ce
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/glue/AccountModule.java
@@ -0,0 +1,51 @@
+/*
+ * 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.account.glue;
+
+import org.skife.config.ConfigurationObjectFactory;
+import org.skife.jdbi.v2.DBI;
+
+import com.google.inject.AbstractModule;
+import com.ning.billing.account.dao.AccountDao;
+import com.ning.billing.account.dao.IAccountDao;
+import com.ning.billing.dbi.DBIProvider;
+import com.ning.billing.dbi.DbiConfig;
+
+public class AccountModule extends AbstractModule {
+
+ protected void installConfig() {
+ final IAccountConfig config = new ConfigurationObjectFactory(System.getProperties()).build(IAccountConfig.class);
+ bind(IAccountConfig.class).toInstance(config);
+ }
+ protected void installDBI() {
+ bind(DBI.class).toProvider(DBIProvider.class).asEagerSingleton();
+ final DbiConfig config = new ConfigurationObjectFactory(System.getProperties()).build(DbiConfig.class);
+ bind(DbiConfig.class).toInstance(config);
+ }
+
+ protected void installAccountDao() {
+ bind(IAccountDao.class).to(AccountDao.class).asEagerSingleton();
+ }
+
+ @Override
+ protected void configure() {
+ installConfig();
+ installDBI();
+ installAccountDao();
+ }
+
+}
diff --git a/account/src/main/java/com/ning/billing/account/glue/IAccountConfig.java b/account/src/main/java/com/ning/billing/account/glue/IAccountConfig.java
new file mode 100644
index 0000000..c95c351
--- /dev/null
+++ b/account/src/main/java/com/ning/billing/account/glue/IAccountConfig.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.account.glue;
+
+public interface IAccountConfig {
+
+}
account/src/main/resources/ddl.sql 10(+10 -0)
diff --git a/account/src/main/resources/ddl.sql b/account/src/main/resources/ddl.sql
new file mode 100644
index 0000000..996af37
--- /dev/null
+++ b/account/src/main/resources/ddl.sql
@@ -0,0 +1,10 @@
+CREATE DATABASE IF NOT EXISTS killbill;
+
+USE killbill;
+
+DROP TABLE IF EXISTS accounts;
+CREATE TABLE accounts (
+ id char(36) NOT NULL,
+ key_name varchar(128) NOT NULL,
+ PRIMARY KEY(id)
+) ENGINE=innodb;
diff --git a/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java b/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java
new file mode 100644
index 0000000..2903bce
--- /dev/null
+++ b/account/src/test/java/com/ning/billing/account/dao/TestSimpleAccountDao.java
@@ -0,0 +1,92 @@
+/*
+ * 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.account.dao;
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.assertFalse;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.ning.billing.account.api.Account;
+import com.ning.billing.account.api.IAccount;
+import com.ning.billing.account.glue.AccountModule;
+
+public class TestSimpleAccountDao {
+
+
+ private IAccountDao dao;
+
+ public static void loadSystemPropertiesFromClasspath( final String resource) {
+ final URL url = TestSimpleAccountDao.class.getResource(resource);
+ assertNotNull(url);
+
+ try {
+ System.getProperties().load( url.openStream() );
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+
+ private Injector getInjector() {
+ return Guice.createInjector(Stage.DEVELOPMENT, new AccountModule());
+ }
+
+
+ @BeforeClass(groups={"setup"})
+ public void setup() {
+ //loadSystemPropertiesFromClasspath("/account.properties");
+ final Injector g = getInjector();
+
+ dao = g.getInstance(IAccountDao.class);
+ }
+
+ @Test(enabled=true, groups={"sql"})
+ public void testBasic() {
+
+ IAccount a = new Account("foo");
+ dao.createAccount(a);
+
+ IAccount r = dao.getAccountByKey("foo");
+ assertNotNull(r);
+ assertEquals(r.getId(), a.getId());
+ assertEquals(r.getKey(), a.getKey());
+
+ r = dao.getAccountFromId(a.getId());
+ assertNotNull(r);
+ assertEquals(r.getId(), a.getId());
+ assertEquals(r.getKey(), a.getKey());
+
+ List<IAccount> all = dao.getAccounts();
+ assertNotNull(all);
+ assertEquals(all.size(), 1);
+ }
+
+
+}
account/src/test/resources/log4j.xml 36(+36 -0)
diff --git a/account/src/test/resources/log4j.xml b/account/src/test/resources/log4j.xml
new file mode 100644
index 0000000..11c2c9c
--- /dev/null
+++ b/account/src/test/resources/log4j.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+ <appender name="stdout" class="org.apache.log4j.ConsoleAppender">
+ <param name="Target" value="System.out"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="%p %d{ISO8601} %X{trace} %t %c %m%n"/>
+ </layout>
+ </appender>
+
+
+ <logger name="com.ning.billing.account">
+ <level value="debug"/>
+ </logger>
+
+ <root>
+ <priority value="info"/>
+ <appender-ref ref="stdout"/>
+ </root>
+</log4j:configuration>
analytics/pom.xml 2(+1 -1)
diff --git a/analytics/pom.xml b/analytics/pom.xml
index 4bda36b..de64a5c 100644
--- a/analytics/pom.xml
+++ b/analytics/pom.xml
@@ -48,7 +48,7 @@
</dependency>
<dependency>
<groupId>com.ning.jetty</groupId>
- <artifactId>ning-service-skeleton-core</artifactId>
+ <artifactId>ning-service-skeleton-utils</artifactId>
</dependency>
<dependency>
<groupId>commons-io</groupId>
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
index 0940d13..3d04806 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscription.java
@@ -82,8 +82,8 @@ public class BusinessSubscription
final IProduct product = currentPlan.getProduct();
productName = product.getName();
productCategory = product.getCategory();
- if (product.getType() != null) {
- productType = product.getType().getName();
+ if (product.getCatalogName() != null) {
+ productType = product.getCatalogName();
}
else {
productType = null;
diff --git a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionEvent.java b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionEvent.java
index 956339e..f0d503d 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionEvent.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/BusinessSubscriptionEvent.java
@@ -128,7 +128,7 @@ public class BusinessSubscriptionEvent
final IPlan currentPlan = subscription.getCurrentPlan();
if (currentPlan != null && currentPlan.getProduct() != null) {
final IProduct product = currentPlan.getProduct();
- if (product.getType() != null && product.getCategory() != null) {
+ if (product.getCatalogName() != null && product.getCategory() != null) {
return product.getCategory();
}
}
diff --git a/analytics/src/main/java/com/ning/billing/analytics/setup/AnalyticsModule.java b/analytics/src/main/java/com/ning/billing/analytics/setup/AnalyticsModule.java
index b50ad8c..efeb970 100644
--- a/analytics/src/main/java/com/ning/billing/analytics/setup/AnalyticsModule.java
+++ b/analytics/src/main/java/com/ning/billing/analytics/setup/AnalyticsModule.java
@@ -19,7 +19,8 @@ package com.ning.billing.analytics.setup;
import com.google.inject.AbstractModule;
import com.ning.billing.analytics.dao.EventDao;
import com.ning.billing.analytics.dao.EventDaoProvider;
-import com.ning.jetty.core.providers.DBIProvider;
+import com.ning.jetty.utils.providers.DBIProvider;
+
import org.skife.jdbi.v2.DBI;
public class AnalyticsModule extends AbstractModule
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java b/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
index fefa76c..a2baa37 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockPlan.java
@@ -21,7 +21,7 @@ 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.catalog.api.PlanAlignment;
+import com.ning.billing.catalog.api.PlanAlignmentChange;
import java.util.Iterator;
@@ -73,18 +73,6 @@ public class MockPlan implements IPlan
}
@Override
- public BillingAlignment getBillingAlignment()
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public PlanAlignment getPlanAlignment()
- {
- throw new UnsupportedOperationException();
- }
-
- @Override
public int getPlansAllowedInBundle()
{
throw new UnsupportedOperationException();
diff --git a/analytics/src/test/java/com/ning/billing/analytics/MockProduct.java b/analytics/src/test/java/com/ning/billing/analytics/MockProduct.java
index 62d7b5a..958de9a 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/MockProduct.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/MockProduct.java
@@ -17,7 +17,6 @@
package com.ning.billing.analytics;
import com.ning.billing.catalog.api.IProduct;
-import com.ning.billing.catalog.api.IProductType;
import com.ning.billing.catalog.api.ProductCategory;
public class MockProduct implements IProduct
@@ -34,16 +33,9 @@ public class MockProduct implements IProduct
}
@Override
- public IProductType getType()
+ public String getCatalogName()
{
- return new IProductType()
- {
- @Override
- public String getName()
- {
- return type;
- }
- };
+ return type;
}
@Override
diff --git a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java
index 79a81f1..7ac53fd 100644
--- a/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java
+++ b/analytics/src/test/java/com/ning/billing/analytics/TestBusinessSubscription.java
@@ -85,7 +85,7 @@ public class TestBusinessSubscription
Assert.assertEquals(subscription.getPrice(), phase.getRecurringPrice().getPrice(null));
Assert.assertEquals(subscription.getProductCategory(), product.getCategory());
Assert.assertEquals(subscription.getProductName(), product.getName());
- Assert.assertEquals(subscription.getProductType(), product.getType().getName());
+ Assert.assertEquals(subscription.getProductType(), product.getCatalogName());
Assert.assertEquals(subscription.getStartDate(), isubscription.getStartDate());
}
api/pom.xml 5(+5 -0)
diff --git a/api/pom.xml b/api/pom.xml
index d38ffe1..ac32a68 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -49,6 +49,11 @@
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.skife.config</groupId>
+ <artifactId>config-magic</artifactId>
+ </dependency>
+
</dependencies>
<build>
</build>
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 0e533b1..f583753 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
@@ -21,16 +21,12 @@ import java.util.List;
public interface ICatalog {
- public abstract IProductType[] getProductTypes();
-
public abstract IProduct[] getProducts();
public abstract IPriceList[] getPriceLists();
public abstract IPriceList getPriceListFromName(String priceListName);
- public abstract List<IProduct> getProductsForType(IProductType productType);
-
public abstract IPlan getPlan(String productName, BillingPeriod term, String priceList);
public abstract Currency[] getSupportedCurrencies();
@@ -52,7 +48,16 @@ public interface ICatalog {
public abstract ActionPolicy getPlanCancelPolicy(PlanPhaseSpecifier planPhase);
- public abstract PlanAlignment getPlanAlignment(PlanPhaseSpecifier from, PlanSpecifier to);
+ public abstract void configureEffectiveDate(Date date);
+
+ public abstract String getCalalogName();
+
+ public abstract PlanAlignmentCreate getPlanCreateAlignment(PlanSpecifier specifier);
+
+ public abstract BillingAlignment getBillingAlignment(PlanPhaseSpecifier planPhase);
+
+ public abstract PlanAlignmentChange getPlanChangeAlignment(PlanPhaseSpecifier from,
+ PlanSpecifier to);
}
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/catalog/api/IPlan.java b/api/src/main/java/com/ning/billing/catalog/api/IPlan.java
index e9efa97..cb13510 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/IPlan.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/IPlan.java
@@ -32,8 +32,6 @@ public interface IPlan {
public abstract BillingPeriod getBillingPeriod();
- public abstract BillingAlignment getBillingAlignment();
-
public abstract int getPlansAllowedInBundle();
}
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/catalog/api/IProduct.java b/api/src/main/java/com/ning/billing/catalog/api/IProduct.java
index af82794..7ea2a21 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/IProduct.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/IProduct.java
@@ -19,8 +19,6 @@ package com.ning.billing.catalog.api;
public interface IProduct {
- public abstract IProductType getType();
-
public abstract String getName();
public abstract IProduct[] getAvailable();
@@ -29,4 +27,6 @@ public interface IProduct {
public abstract ProductCategory getCategory();
+ public abstract String getCatalogName();
+
}
\ No newline at end of file
diff --git a/api/src/main/java/com/ning/billing/catalog/api/PlanPhaseSpecifier.java b/api/src/main/java/com/ning/billing/catalog/api/PlanPhaseSpecifier.java
index 281a81c..4dcfa58 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/PlanPhaseSpecifier.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/PlanPhaseSpecifier.java
@@ -20,9 +20,9 @@ public class PlanPhaseSpecifier extends PlanSpecifier {
private final PhaseType phaseType;
- public PlanPhaseSpecifier(String productName, BillingPeriod billingPeriod,
+ public PlanPhaseSpecifier(String productName, ProductCategory productCategory, BillingPeriod billingPeriod,
String priceListName, PhaseType phaseType) {
- super(productName, billingPeriod, priceListName);
+ super(productName, productCategory, billingPeriod, priceListName);
this.phaseType = phaseType;
}
diff --git a/api/src/main/java/com/ning/billing/catalog/api/PlanSpecifier.java b/api/src/main/java/com/ning/billing/catalog/api/PlanSpecifier.java
index face0da..92b6bc4 100644
--- a/api/src/main/java/com/ning/billing/catalog/api/PlanSpecifier.java
+++ b/api/src/main/java/com/ning/billing/catalog/api/PlanSpecifier.java
@@ -18,13 +18,15 @@ package com.ning.billing.catalog.api;
public class PlanSpecifier {
private final String productName;
+ private final ProductCategory productCategory;
private final BillingPeriod billingPeriod;
private final String priceListName;
- public PlanSpecifier(String productName, BillingPeriod billingPeriod,
+ public PlanSpecifier(String productName, ProductCategory productCategory, BillingPeriod billingPeriod,
String priceListName) {
super();
this.productName = productName;
+ this.productCategory = productCategory;
this.billingPeriod = billingPeriod;
this.priceListName = priceListName;
}
@@ -32,6 +34,9 @@ public class PlanSpecifier {
public String getProductName() {
return productName;
}
+ public ProductCategory getProductCategory() {
+ return productCategory;
+ }
public BillingPeriod getBillingPeriod() {
return billingPeriod;
}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/CaseBillingAlignment.java b/catalog/src/main/java/com/ning/billing/catalog/CaseBillingAlignment.java
new file mode 100644
index 0000000..57dd49c
--- /dev/null
+++ b/catalog/src/main/java/com/ning/billing/catalog/CaseBillingAlignment.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.catalog;
+
+import javax.xml.bind.annotation.XmlElement;
+
+import com.ning.billing.catalog.api.BillingAlignment;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.ProductCategory;
+
+public class CaseBillingAlignment extends CasePhase<BillingAlignment> {
+
+ @XmlElement(required=true)
+ private BillingAlignment alignment;
+
+ public CaseBillingAlignment() {}
+
+ public CaseBillingAlignment(Product product, ProductCategory productCategory, BillingPeriod billingPeriod,
+ PriceList priceList, PhaseType phaseType, BillingAlignment alignment) {
+ super(product, productCategory, billingPeriod, priceList, phaseType, alignment);
+ this.alignment = alignment;
+ }
+
+ @Override
+ protected BillingAlignment getResult() {
+ return alignment;
+ }
+}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/CaseCancelPolicy.java b/catalog/src/main/java/com/ning/billing/catalog/CaseCancelPolicy.java
new file mode 100644
index 0000000..700d6be
--- /dev/null
+++ b/catalog/src/main/java/com/ning/billing/catalog/CaseCancelPolicy.java
@@ -0,0 +1,46 @@
+/*
+ * 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 javax.xml.bind.annotation.XmlElement;
+
+import com.ning.billing.catalog.api.ActionPolicy;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.ProductCategory;
+
+public class CaseCancelPolicy extends CasePhase<ActionPolicy>{
+
+ @XmlElement(required=true)
+ private ActionPolicy policy;
+
+ public CaseCancelPolicy() {}
+
+ public CaseCancelPolicy(Product product, ProductCategory productCategory, BillingPeriod billingPeriod, PriceList priceList,
+ PhaseType phaseType, ActionPolicy policy) {
+ super(product, productCategory, billingPeriod, priceList, phaseType, policy);
+ this.policy = policy;
+ }
+
+
+
+ @Override
+ protected ActionPolicy getResult() {
+ return policy;
+ }
+
+}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/CaseChangePlanAlignment.java b/catalog/src/main/java/com/ning/billing/catalog/CaseChangePlanAlignment.java
new file mode 100644
index 0000000..a00ebb4
--- /dev/null
+++ b/catalog/src/main/java/com/ning/billing/catalog/CaseChangePlanAlignment.java
@@ -0,0 +1,54 @@
+/*
+ * 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 javax.xml.bind.annotation.XmlElement;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.PlanAlignmentChange;
+import com.ning.billing.catalog.api.ProductCategory;
+
+public class CaseChangePlanAlignment extends CaseChange<PlanAlignmentChange> {
+
+ @XmlElement(required=true)
+ private PlanAlignmentChange alignment;
+
+ public CaseChangePlanAlignment() {}
+
+ protected CaseChangePlanAlignment(
+ Product from, Product to,
+ ProductCategory fromProductCategory, ProductCategory toProductCategory,
+ BillingPeriod fromBP,BillingPeriod toBP,
+ PriceList fromPriceList, PriceList toPriceList,
+ PhaseType fromType,
+ PlanAlignmentChange result) {
+ super(from, to,
+ fromProductCategory, toProductCategory,
+ fromBP, toBP,
+ fromPriceList, toPriceList,
+ fromType,
+ result);
+ alignment = result;
+ }
+
+ @Override
+ protected PlanAlignmentChange getResult() {
+ return alignment;
+ }
+
+}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/CaseChangePlanPolicy.java b/catalog/src/main/java/com/ning/billing/catalog/CaseChangePlanPolicy.java
new file mode 100644
index 0000000..258b9cd
--- /dev/null
+++ b/catalog/src/main/java/com/ning/billing/catalog/CaseChangePlanPolicy.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 javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlSeeAlso;
+
+import com.ning.billing.catalog.api.ActionPolicy;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.ProductCategory;
+
+@XmlSeeAlso(CaseChange.class)
+public class CaseChangePlanPolicy extends CaseChange<ActionPolicy> {
+
+ @XmlElement(required=true)
+ private ActionPolicy policy;
+
+ public CaseChangePlanPolicy() {}
+
+ protected CaseChangePlanPolicy(
+ Product from, Product to,
+ ProductCategory fromProductCategory, ProductCategory toProductCategory,
+ BillingPeriod fromBP,BillingPeriod toBP,
+ PriceList fromPriceList, PriceList toPriceList,
+ PhaseType fromType,
+ ActionPolicy result) {
+ super(from, to,
+ fromProductCategory, toProductCategory,
+ fromBP, toBP,
+ fromPriceList, toPriceList,
+ fromType,
+ result);
+ policy = result;
+ }
+
+
+
+ @Override
+ protected ActionPolicy getResult() {
+ return policy;
+ }
+
+}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/CaseCreateAlignment.java b/catalog/src/main/java/com/ning/billing/catalog/CaseCreateAlignment.java
new file mode 100644
index 0000000..3a1ba1f
--- /dev/null
+++ b/catalog/src/main/java/com/ning/billing/catalog/CaseCreateAlignment.java
@@ -0,0 +1,44 @@
+/*
+ * 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 javax.xml.bind.annotation.XmlElement;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.PlanAlignmentCreate;
+import com.ning.billing.catalog.api.ProductCategory;
+
+public class CaseCreateAlignment extends Case<PlanAlignmentCreate>{
+
+ @XmlElement(required=true)
+ private PlanAlignmentCreate alignment;
+
+ public CaseCreateAlignment() {}
+
+ public CaseCreateAlignment(Product product, ProductCategory productCategory, BillingPeriod billingPeriod,
+ PriceList priceList, PlanAlignmentCreate alignment) {
+ super(product, productCategory, billingPeriod, priceList, alignment);
+ this.alignment = alignment;
+ }
+
+ @Override
+ protected PlanAlignmentCreate getResult() {
+ return alignment;
+ }
+
+}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/CasePhase.java b/catalog/src/main/java/com/ning/billing/catalog/CasePhase.java
new file mode 100644
index 0000000..e189c5c
--- /dev/null
+++ b/catalog/src/main/java/com/ning/billing/catalog/CasePhase.java
@@ -0,0 +1,70 @@
+/*
+ * 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 javax.xml.bind.annotation.XmlElement;
+
+import com.ning.billing.catalog.ValidatingConfig.ValidationErrors;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.ProductCategory;
+
+public abstract class CasePhase<T> extends Case<T> {
+
+ @XmlElement(required=false)
+ private PhaseType phaseType;
+
+ public CasePhase() {}
+
+ public CasePhase(Product product, ProductCategory productCategory,
+ BillingPeriod billingPeriod, PriceList priceList,
+ PhaseType phaseType, T result) {
+ super(product, productCategory, billingPeriod, priceList, result);
+ this.phaseType = phaseType;
+ }
+
+
+ public T getResult(PlanPhaseSpecifier planPhase, Catalog c) {
+ if (
+ (phaseType == null || planPhase.getPhaseType() == null || planPhase.getPhaseType() == phaseType) &&
+ satisfiesCase(planPhase, c)
+ ) {
+ return getResult();
+ }
+ return null;
+ }
+
+ public static <K> K getResult(Case<K>[] cases, PlanPhaseSpecifier planSpec, Catalog catalog) {
+ if(cases != null) {
+ for(int i = cases.length - 1; i >=0; i --) {
+ K result = cases[i].getResult(planSpec, catalog);
+ if(result != null) {
+ return result;
+ }
+ }
+ }
+ return null;
+
+ }
+
+ @Override
+ public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
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 0618c8e..c83da21 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Catalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Catalog.java
@@ -17,9 +17,7 @@
package com.ning.billing.catalog;
import java.net.URL;
-import java.util.ArrayList;
import java.util.Date;
-import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
@@ -28,33 +26,39 @@ import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import com.ning.billing.catalog.api.ActionPolicy;
+import com.ning.billing.catalog.api.BillingAlignment;
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.IPlan;
import com.ning.billing.catalog.api.IProduct;
-import com.ning.billing.catalog.api.IProductType;
-import com.ning.billing.catalog.api.PlanAlignment;
+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;
@XmlRootElement
@XmlAccessorType(XmlAccessType.NONE)
public class Catalog extends ValidatingConfig implements ICatalog {
+ public PlanRules getPlanRules() {
+ return planRules;
+ }
+
+ public void setPlanRules(PlanRules planRules) {
+ this.planRules = planRules;
+ }
@XmlElement(required=true)
private Date effectiveDate;
+ @XmlElement(required=true)
+ private String catalogName;
+
private URL catalogURL;
@XmlElementWrapper(name="currencies", required=true)
@XmlElement(name="currency", required=true)
private Currency[] supportedCurrencies;
- @XmlElementWrapper(name="productTypes", required=true)
- @XmlElement(name="productType", required=true)
- private ProductType[] productTypes;
-
@XmlElementWrapper(name="products", required=true)
@XmlElement(name="product", required=true)
private Product[] products;
@@ -93,12 +97,12 @@ public class Catalog extends ValidatingConfig implements ICatalog {
}
/* (non-Javadoc)
- * @see com.ning.billing.catalog.ICatalog#getProductTypes()
+ * @see com.ning.billing.catalog.ICatalog#getCalalogName()
*/
@Override
- public ProductType[] getProductTypes() {
- return productTypes;
- }
+ public String getCalalogName() {
+ return catalogName;
+ }
/* (non-Javadoc)
* @see com.ning.billing.catalog.ICatalog#getProducts()
@@ -138,20 +142,6 @@ public class Catalog extends ValidatingConfig implements ICatalog {
}
/* (non-Javadoc)
- * @see com.ning.billing.catalog.ICatalog#getProductsForType(com.ning.billing.catalog.ProductType)
- */
- @Override
- public List<IProduct> getProductsForType(IProductType productType) {
- ArrayList<IProduct> result = new ArrayList<IProduct>();
- for(Product p : products) {
- if(p.getType().equals(productType)) {
- result.add(p);
- }
- }
- return result;
- }
-
- /* (non-Javadoc)
* @see com.ning.billing.catalog.ICatalog#getPlan(java.lang.String, java.lang.String)
*/
@Override
@@ -171,10 +161,6 @@ public class Catalog extends ValidatingConfig implements ICatalog {
return null;
}
- public void setProductTypes(ProductType[] productTypes) {
- this.productTypes = productTypes;
- }
-
@Override
public Currency[] getSupportedCurrencies() {
return supportedCurrencies;
@@ -200,7 +186,6 @@ 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, productTypes));
errors.addAll(validate(catalog,errors, priceLists));
errors.addAll(validate(catalog,errors, plans));
errors.addAll(planRules.validate(catalog, errors));
@@ -211,6 +196,11 @@ public class Catalog extends ValidatingConfig implements ICatalog {
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) {
@@ -218,12 +208,20 @@ public class Catalog extends ValidatingConfig implements ICatalog {
}
@Override
- public PlanAlignment getPlanAlignment(PlanPhaseSpecifier from, PlanSpecifier to) {
- return planRules.getPlanAlignment(from, to, this);
+ public PlanAlignmentCreate getPlanCreateAlignment(PlanSpecifier planPhase) {
+ PlanPhaseSpecifier specifier = new PlanPhaseSpecifier(planPhase.getProductName(), planPhase.getProductCategory(), planPhase.getBillingPeriod(), planPhase.getPriceListName(), null);
+
+ return planRules.getPlanCreateAlignment(specifier, this);
}
+
+ @Override
+ public BillingAlignment getBillingAlignment(PlanPhaseSpecifier planPhase) {
+ return planRules.getBillingAlignment(planPhase, this);
+ }
+
@Override
- public IPlan getPlanFromName(String name) {
+ public Plan getPlanFromName(String name) {
if (name == null) {
return null;
}
@@ -297,6 +295,12 @@ public class Catalog extends ValidatingConfig implements ICatalog {
public void setPriceLists(PriceList[] priceLists) {
this.priceLists = priceLists;
}
+
+ @Override
+ public void configureEffectiveDate(Date date) {
+ // Nothing to do here this is a method that is only inplemented on VersionedCatalog
+
+ }
//TODO: MDW validation - only allow one default pricelist
diff --git a/catalog/src/main/java/com/ning/billing/catalog/ICatalogConfiguration.java b/catalog/src/main/java/com/ning/billing/catalog/ICatalogConfiguration.java
new file mode 100644
index 0000000..394802d
--- /dev/null
+++ b/catalog/src/main/java/com/ning/billing/catalog/ICatalogConfiguration.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;
+
+import org.skife.config.Config;
+
+public interface ICatalogConfiguration {
+
+ @Config("killbill.catalog.config.directory")
+ public String getCatalogDirectoryURL();
+
+}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/io/ICatalogLoader.java b/catalog/src/main/java/com/ning/billing/catalog/io/ICatalogLoader.java
new file mode 100644
index 0000000..426f7c6
--- /dev/null
+++ b/catalog/src/main/java/com/ning/billing/catalog/io/ICatalogLoader.java
@@ -0,0 +1,34 @@
+/*
+ * 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.io;
+
+import java.io.IOException;
+import java.net.URL;
+
+import javax.xml.bind.JAXBException;
+
+import org.xml.sax.SAXException;
+
+import com.ning.billing.catalog.VersionedCatalog;
+import com.ning.billing.catalog.api.InvalidConfigException;
+
+public interface ICatalogLoader {
+
+ public abstract VersionedCatalog load(URL url) throws IOException,
+ SAXException, InvalidConfigException, JAXBException;
+
+}
\ No newline at end of file
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 9c795cb..59bffa3 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
@@ -33,13 +33,17 @@ import com.ning.billing.catalog.Catalog;
import com.ning.billing.catalog.VersionedCatalog;
import com.ning.billing.catalog.api.InvalidConfigException;
-public class VersionedCatalogLoader {
- private static final String XML_EXTENSION = ".xml";
- private static final String HREF_LOW_START = "href=\"";
- private static final String HREF_CAPS_START = "HREF=\"";
- private static final String HREF_SEARCH_END = "\"";
+public class VersionedCatalogLoader implements ICatalogLoader {
+ 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 = "\"";
- public static VersionedCatalog load(URL url) throws IOException, SAXException, InvalidConfigException, JAXBException {
+ /* (non-Javadoc)
+ * @see com.ning.billing.catalog.io.ICatalogLoader#load(java.net.URL)
+ */
+ @Override
+ public VersionedCatalog load(URL url) throws IOException, SAXException, InvalidConfigException, JAXBException {
String directoryContents = pullContentsFrom(url);
List<URL> xmlURLs = findXmlReferences(directoryContents, url);
VersionedCatalog result = new VersionedCatalog();
@@ -50,14 +54,14 @@ public class VersionedCatalogLoader {
return result;
}
- protected static List<URL> findXmlReferences(String directoryContents, URL url) throws MalformedURLException {
+ protected List<URL> findXmlReferences(String directoryContents, URL url) throws MalformedURLException {
if(url.getProtocol().equals("file")) {
return findXmlFileReferences(directoryContents, url);
}
return findXmlUrlReferences(directoryContents, url);
}
- protected static List<URL> findXmlUrlReferences(String directoryContents, URL url) throws MalformedURLException {
+ protected List<URL> findXmlUrlReferences(String directoryContents, URL url) throws MalformedURLException {
List<URL> results = new ArrayList<URL>();
List<String> urlFragments = extractHrefs(directoryContents);
for(String u : urlFragments) {
@@ -74,7 +78,7 @@ public class VersionedCatalogLoader {
return results;
}
- protected static List<String> extractHrefs(String directoryContents) {
+ protected List<String> extractHrefs(String directoryContents) {
List<String> results = new ArrayList<String>();
int start = 0;
int end = 0;
@@ -102,7 +106,7 @@ public class VersionedCatalogLoader {
return results;
}
- protected static List<URL> findXmlFileReferences(String directoryContents, URL url) throws MalformedURLException {
+ protected List<URL> findXmlFileReferences(String directoryContents, URL url) throws MalformedURLException {
List<URL> results = new ArrayList<URL>();
String[] filenames = directoryContents.split("\\n");
for(String filename : filenames) {
@@ -113,7 +117,7 @@ public class VersionedCatalogLoader {
return results;
}
- protected static URL appendToURL(final URL url, final String filename) throws MalformedURLException {
+ protected URL appendToURL(final URL url, final String filename) throws MalformedURLException {
String f = filename;
if (!url.toString().endsWith("/")) {
f = "/" + filename;
@@ -121,14 +125,9 @@ public class VersionedCatalogLoader {
return new URL(url.toString() + f);
}
- protected static String pullContentsFrom(final URL url) throws IOException {
+ protected String pullContentsFrom(final URL url) throws IOException {
URLConnection connection = url.openConnection();
InputStream content = connection.getInputStream();
return new Scanner(content).useDelimiter("\\A").next();
}
-
- public static void main (String[] args) throws Exception {
- //new VersionedCatalog().initialize(new URL("http://gepo.ningops.net/config/trunk/xno/viking/master/viking-core/"));
- new VersionedCatalogLoader().load(new URL("file:///Users/mwesthead/work/killbill/catalog/src/test/resources/"));
- }
}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/io/XMLReader.java b/catalog/src/main/java/com/ning/billing/catalog/io/XMLReader.java
index 1d77249..1f568ea 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/io/XMLReader.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/io/XMLReader.java
@@ -16,8 +16,6 @@
package com.ning.billing.catalog.io;
-import java.io.File;
-import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
@@ -25,7 +23,6 @@ import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
-import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
@@ -33,12 +30,6 @@ import javax.xml.validation.SchemaFactory;
import org.xml.sax.SAXException;
import com.ning.billing.catalog.Catalog;
-import com.ning.billing.catalog.Duration;
-import com.ning.billing.catalog.Plan;
-import com.ning.billing.catalog.PlanPhase;
-import com.ning.billing.catalog.PriceList;
-import com.ning.billing.catalog.Product;
-import com.ning.billing.catalog.ProductType;
import com.ning.billing.catalog.ValidatingConfig.ValidationErrors;
import com.ning.billing.catalog.api.InvalidConfigException;
@@ -46,7 +37,7 @@ public class XMLReader {
public static Catalog getCatalogFromName(URL url) throws SAXException, InvalidConfigException, JAXBException {
- JAXBContext context =JAXBContext.newInstance(Catalog.class,Plan.class,Duration.class, Product.class, ProductType.class, PlanPhase.class, PriceList.class);
+ JAXBContext context =JAXBContext.newInstance(Catalog.class);
InputStream resourceStream = XMLReader.class.getResourceAsStream("/CatalogSchema.xsd");
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI );
@@ -68,17 +59,5 @@ public class XMLReader {
return null;
}
}
- /**
- * @param args
- * @throws SAXException
- * @throws InvalidConfigException
- */
- public static void main(String[] args) throws IOException, TransformerException, JAXBException, SAXException, InvalidConfigException {
- String curDir = System.getProperty("user.dir");
- getCatalogFromName(new File("src/test/resources/WeaponsHire.xml").toURI().toURL());
- getCatalogFromName(new File("src/test/resources/WeaponsHireSmall.xml").toURI().toURL());
-
- }
-
}
diff --git a/catalog/src/main/java/com/ning/billing/catalog/io/XMLSchemaGenerator.java b/catalog/src/main/java/com/ning/billing/catalog/io/XMLSchemaGenerator.java
index c28eccc..ae41c61 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/io/XMLSchemaGenerator.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/io/XMLSchemaGenerator.java
@@ -37,17 +37,12 @@ import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import com.ning.billing.catalog.Catalog;
-import com.ning.billing.catalog.Duration;
-import com.ning.billing.catalog.Plan;
-import com.ning.billing.catalog.PlanPhase;
-import com.ning.billing.catalog.PriceList;
-import com.ning.billing.catalog.Product;
-import com.ning.billing.catalog.ProductType;
public class XMLSchemaGenerator {
+ //Note: this main method is called byt the maven build to generate the schema for the jar
public static void main(String[] args) throws IOException, TransformerException, JAXBException {
- JAXBContext context =JAXBContext.newInstance(Catalog.class,Plan.class,Duration.class, Product.class, ProductType.class, PlanPhase.class, PriceList.class);
+ JAXBContext context =JAXBContext.newInstance(Catalog.class);
String xsdFileName = "CatalogSchema.xsd";
if(args.length != 0) {
xsdFileName = args[0] + "/" + xsdFileName;
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 10e80aa..a220cf7 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Plan.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Plan.java
@@ -52,9 +52,6 @@ public class Plan extends ValidatingConfig implements IPlan {
@XmlElement(name="finalPhase", required=true)
private PlanPhase finalPhase;
- @XmlElement(required=true)
- private BillingAlignment billingAlignment;
-
//If this is missing it defaults to 1
//No other value is allowed for BASE plans.
//No other value is allowed for Tiered ADDONS
@@ -135,7 +132,6 @@ public class Plan extends ValidatingConfig implements IPlan {
@Override
public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
return errors;
-
}
@Override
@@ -153,18 +149,6 @@ public class Plan extends ValidatingConfig implements IPlan {
}
/* (non-Javadoc)
- * @see com.ning.billing.catalog.IPlan#getBillingAlignment()
- */
- @Override
- public BillingAlignment getBillingAlignment() {
- return billingAlignment;
- }
-
- public void setBillingAlignment(BillingAlignment billingAlignment) {
- this.billingAlignment = billingAlignment;
- }
-
- /* (non-Javadoc)
* @see com.ning.billing.catalog.IPlan#getPlansAllowedInBundle()
*/
@Override
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 2d742a2..34b372f 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/PlanRules.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/PlanRules.java
@@ -22,9 +22,11 @@ import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import com.ning.billing.catalog.api.ActionPolicy;
+import com.ning.billing.catalog.api.BillingAlignment;
import com.ning.billing.catalog.api.BillingPeriod;
import com.ning.billing.catalog.api.IProduct;
-import com.ning.billing.catalog.api.PlanAlignment;
+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;
@@ -35,63 +37,62 @@ public class PlanRules extends ValidatingConfig {
@XmlElement(name="tier", required=false) // may not have tiers in some catalogs
private ProductTier[] productTiers;
- @XmlElement(name="changeRule", required=true)
- private PlanChangeRule[] rules;
+ @XmlElement(name="changePolicyRule", required=true)
+ private PlanPolicyChangeRule[] rules;
- @XmlElement(name="changeCase", required=false)
- private PlanChangeCase[] changeCase;
+ @XmlElement(name="changePolicyCase", required=false)
+ private CaseChangePlanPolicy[] changeCase;
- @XmlElement(name="cancelCase", required=false)
- private PlanCancelCase[] cancelCase;
+ @XmlElement(name="changeAlignmentCase", required=false)
+ private CaseChangePlanAlignment[] changeAlignmentCase;
- @XmlElement(name="alignmentCase", required=false)
- private PlanAlignmentCase[] alignmentCase;
+ @XmlElement(name="cancelPolicyCase", required=false)
+ private CaseCancelPolicy[] cancelCase;
- public PlanChangeRule[] getRules() {
- return rules;
- }
-
- public void setGeneralRules(PlanChangeRule[] generalRules) {
- this.rules = generalRules;
- }
-
- public PlanChangeCase[] getSpecialCase() {
- return changeCase;
- }
-
- protected void setSpecialCaseRules(PlanChangeCase[] specialchangeCaseCaseRules) {
- this.changeCase = specialchangeCaseCaseRules;
- }
-
- protected void setCancelCaseRules(PlanCancelCase[] cancelCase) {
- this.cancelCase = cancelCase;
- }
+ @XmlElement(name="createAlignmentCase", required=false)
+ private CaseCreateAlignment[] createAlignmentCase;
- public void setAlignmentCase(PlanAlignmentCase[] alignmentCase) {
- this.alignmentCase = alignmentCase;
- }
+ @XmlElement(name="billingAlignmentCase", required=false)
+ private CaseBillingAlignment[] billingAlignmentCase;
@Override
public ValidationErrors validate(Catalog catalog, ValidationErrors errors) {
return errors;
}
+
+ public PlanRules(){}
+
+ //For test
+ protected PlanRules(ProductTier[] productTiers, PlanPolicyChangeRule[] rules,
+ CaseChangePlanPolicy[] changeCase, CaseCancelPolicy[] cancelCase,
+ CaseChangePlanAlignment[] changeAlignmentCase,
+ CaseCreateAlignment[] createAlignmentCase) {
+ super();
+ this.productTiers = productTiers;
+ this.rules = rules;
+ this.changeCase = changeCase;
+ this.cancelCase = cancelCase;
+ this.changeAlignmentCase = changeAlignmentCase;
+ this.createAlignmentCase = createAlignmentCase;
+ }
public ActionPolicy getPlanChangePolicy(PlanPhaseSpecifier from,
PlanSpecifier to, Catalog catalog) {
- if(changeCase != null) {
- for(int i = changeCase.length - 1; i >=0; i --) {
- ActionPolicy policy = changeCase[i].getPlanChangePolicy(from, to, catalog);
- if (policy != null) { return policy; }
- }
- }
+
+ ActionPolicy policy = CaseChange.getResult(changeCase, from, to, catalog);
+ if (policy != null) {
+ return policy;
+ }
+
+
for(int i = rules.length - 1; i >=0; i --) {
int fromProductIndex = getProductIndex(catalog.getProductFromName(from.getProductName()));
int fromBillingPeriodIndex = getBillingPeriodIndex(from.getBillingPeriod());
int toProductIndex = getProductIndex(catalog.getProductFromName(to.getProductName()));
int toBillingPeriodIndex = getBillingPeriodIndex(to.getBillingPeriod());
- ActionPolicy policy = rules[i].getPlanChangePolicy(
+ policy = rules[i].getPlanChangePolicy(
fromProductIndex, fromBillingPeriodIndex,
toProductIndex, toBillingPeriodIndex,
from.getPhaseType());
@@ -100,39 +101,7 @@ public class PlanRules extends ValidatingConfig {
return null;
}
-
- public PlanAlignment getPlanAlignment(PlanPhaseSpecifier from,
- PlanSpecifier to, Catalog catalog) {
- if(alignmentCase != null) {
- for(int i = alignmentCase.length - 1; i >=0; i --) {
- PlanAlignment alignment = alignmentCase[i].getPlanAlignment(from, to, catalog);
- if(alignment != null) {
- return alignment;
- }
- }
- }
- return null;
-
- }
-
- public ActionPolicy getPlanCancelPolicy(PlanPhaseSpecifier planPhase, Catalog catalog) {
- if(cancelCase != null) {
- for(int i = cancelCase.length - 1; i >=0; i --) {
- ActionPolicy policy = cancelCase[i].getPlanCancelPolicy(planPhase, catalog);
- if (policy != null) {
- return policy;
- }
- }
- }
-
- return null;
- }
-
- private int getBillingPeriodIndex(BillingPeriod src) {
- return src.ordinal();
- }
-
private int getProductIndex(IProduct src) {
for(ProductTier tier : productTiers) {
for(int i = 0; i < tier.getProducts().length; i++ ){
@@ -143,12 +112,34 @@ public class PlanRules extends ValidatingConfig {
}
return 0;
}
+ public PlanAlignmentChange getPlanChangeAlignment(PlanPhaseSpecifier from,
+ PlanSpecifier to, Catalog catalog) {
+ return CaseChange.getResult(changeAlignmentCase, from, to, catalog);
+ }
+
+ public PlanAlignmentCreate getPlanCreateAlignment(PlanPhaseSpecifier planPhase, Catalog catalog) {
+ return Case.getResult(createAlignmentCase, planPhase, catalog);
+ }
+
+ public ActionPolicy getPlanCancelPolicy(PlanPhaseSpecifier planPhase, Catalog catalog) {
+ return Case.getResult(cancelCase, planPhase, catalog);
+ }
+
+ public BillingAlignment getBillingAlignment(PlanPhaseSpecifier planPhase, Catalog catalog) {
+ return Case.getResult(billingAlignmentCase, planPhase, catalog);
+ }
+
+ private int getBillingPeriodIndex(BillingPeriod src) {
+ return src.ordinal();
+ }
+
protected 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/Product.java b/catalog/src/main/java/com/ning/billing/catalog/Product.java
index 253fe1e..310837c 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/Product.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/Product.java
@@ -25,19 +25,15 @@ import javax.xml.bind.annotation.XmlID;
import javax.xml.bind.annotation.XmlIDREF;
import com.ning.billing.catalog.api.IProduct;
-import com.ning.billing.catalog.api.IProductType;
import com.ning.billing.catalog.api.ProductCategory;
@XmlAccessorType(XmlAccessType.NONE)
public class Product extends ValidatingConfig implements IProduct {
-
+
@XmlAttribute (required=true)
@XmlID
private String name;
- @XmlIDREF @XmlElement(required=true)
- private ProductType type;
-
@XmlElement(required=true)
private ProductCategory category;
@@ -48,8 +44,17 @@ public class Product extends ValidatingConfig implements IProduct {
@XmlElementWrapper(name="available", required=false)
@XmlIDREF @XmlElement(name="addonProduct", required=true)
private Product[] available;
+
+ //Not included in XML
+ private String catalogName;
+
@Override
+ public String getCatalogName() {
+ return catalogName;
+ }
+
+ @Override
public ProductCategory getCategory() {
return category;
}
@@ -67,13 +72,9 @@ public class Product extends ValidatingConfig implements IProduct {
public Product() {
}
- protected Product(IProductType type, String name) {
- this.name = name;
- }
-
- @Override
- public ProductType getType() {
- return type;
+ protected Product(String name, ProductCategory category) {
+ this.category = category;
+ this.name = name;
}
@Override
@@ -81,10 +82,6 @@ public class Product extends ValidatingConfig implements IProduct {
return name;
}
- public void setType(ProductType type) {
- this.type = type;
- }
-
public void setName(String name) {
this.name = name;
}
@@ -115,6 +112,12 @@ public class Product extends ValidatingConfig implements IProduct {
}
return false;
}
+
+ @Override
+ public void initialize(Catalog catalog) {
+ catalogName = catalog.getCalalogName();
+ }
+
//TODO: MDW validation: inclusion and exclusion lists can only contain addon products
//TODO: MDW validation: a given product can only be in, at most, one of inclusion and exclusion lists
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 d4aa4c6..055ccd7 100644
--- a/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
+++ b/catalog/src/main/java/com/ning/billing/catalog/VersionedCatalog.java
@@ -23,14 +23,14 @@ import java.util.Iterator;
import java.util.List;
import com.ning.billing.catalog.api.ActionPolicy;
+import com.ning.billing.catalog.api.BillingAlignment;
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.IPlan;
import com.ning.billing.catalog.api.IPlanPhase;
import com.ning.billing.catalog.api.IProduct;
-import com.ning.billing.catalog.api.IProductType;
-import com.ning.billing.catalog.api.PlanAlignment;
+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;
@@ -74,7 +74,8 @@ public class VersionedCatalog extends ValidatingConfig implements ICatalog {
return versions.iterator();
}
- public void applyEffectiveDate(Date date) {
+ @Override
+ public void configureEffectiveDate(Date date) {
currentCatalog = versionForDate(date); //
}
@@ -82,93 +83,58 @@ public class VersionedCatalog extends ValidatingConfig implements ICatalog {
return versions.size();
}
- public boolean equals(Object arg0) {
- return currentCatalog.equals(arg0);
- }
-
- public ProductType[] getProductTypes() {
- return currentCatalog.getProductTypes();
- }
-
+ @Override
public Product[] getProducts() {
return currentCatalog.getProducts();
}
- public void setProducts(Product[] products) {
- currentCatalog.setProducts(products);
- }
-
+ @Override
public PriceList[] getPriceLists() {
return currentCatalog.getPriceLists();
}
- public void setPlanSets(PriceList[] planSets) {
- currentCatalog.setPlanSets(planSets);
- }
-
+ @Override
public PriceList getPriceListFromName(String planSetName) {
return currentCatalog.getPriceListFromName(planSetName);
}
- public List<IProduct> getProductsForType(IProductType productType) {
- return currentCatalog.getProductsForType(productType);
- }
-
+ @Override
public Plan getPlan(String productName, BillingPeriod term,
String planSetName) {
return currentCatalog.getPlan(productName, term, planSetName);
}
- public void setProductTypes(ProductType[] productTypes) {
- currentCatalog.setProductTypes(productTypes);
- }
-
+ @Override
public Currency[] getSupportedCurrencies() {
return currentCatalog.getSupportedCurrencies();
}
+ @Override
public Plan[] getPlans() {
return currentCatalog.getPlans();
}
- public IPlan getPlanFromName(String name) {
+ @Override
+ public Plan getPlanFromName(String name) {
return currentCatalog.getPlanFromName(name);
}
+
+ @Override
public IPlanPhase getPhaseFromName(String name) {
return currentCatalog.getPhaseFromName(name);
}
+ @Override
public Date getEffectiveDate() {
return currentCatalog.getEffectiveDate();
}
- public int hashCode() {
- return currentCatalog.hashCode();
- }
-
+ @Override
public void initialize(Catalog catalog) {
- currentCatalog.initialize(catalog);
- }
-
- public void setSupportedCurrencies(Currency[] supportedCurrencies) {
- currentCatalog.setSupportedCurrencies(supportedCurrencies);
- }
-
- public void setPlanChangeRules(PlanRules planChangeRules) {
- currentCatalog.setPlanChangeRules(planChangeRules);
- }
-
- public void setPlans(Plan[] plans) {
- currentCatalog.setPlans(plans);
- }
-
- public void setEffectiveDate(Date effectiveDate) {
- currentCatalog.setEffectiveDate(effectiveDate);
- }
-
- public String toString() {
- return currentCatalog.toString();
+ for(Catalog c : versions) {
+ c.initialize(catalog);
+ }
}
@Override
@@ -202,9 +168,27 @@ public class VersionedCatalog extends ValidatingConfig implements ICatalog {
}
@Override
- public PlanAlignment getPlanAlignment(PlanPhaseSpecifier from,
+ public PlanAlignmentChange getPlanChangeAlignment(PlanPhaseSpecifier from,
PlanSpecifier to) {
- return currentCatalog.getPlanAlignment(from, to);
+ return currentCatalog.getPlanChangeAlignment(from, to);
+ }
+
+ @Override
+ public PlanAlignmentCreate getPlanCreateAlignment(PlanSpecifier specifier) {
+ return currentCatalog.getPlanCreateAlignment(specifier);
+ }
+
+ @Override
+ public String getCalalogName() {
+ return currentCatalog.getCalalogName();
+ }
+
+ @Override
+ public BillingAlignment getBillingAlignment(PlanPhaseSpecifier planPhase) {
+ return currentCatalog.getBillingAlignment(planPhase);
}
+
+ //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/io/TestVersionedCatalogLoader.java b/catalog/src/test/java/com/ning/billing/catalog/io/TestVersionedCatalogLoader.java
index 1e978a2..c8efd11 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
@@ -15,12 +15,6 @@
*/
package com.ning.billing.catalog.io;
-import static com.ning.billing.catalog.io.VersionedCatalogLoader.appendToURL;
-import static com.ning.billing.catalog.io.VersionedCatalogLoader.extractHrefs;
-import static com.ning.billing.catalog.io.VersionedCatalogLoader.findXmlFileReferences;
-import static com.ning.billing.catalog.io.VersionedCatalogLoader.findXmlUrlReferences;
-import static com.ning.billing.catalog.io.VersionedCatalogLoader.load;
-import static com.ning.billing.catalog.io.VersionedCatalogLoader.pullContentsFrom;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
@@ -28,7 +22,6 @@ import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.Date;
import java.util.Iterator;
import java.util.List;
@@ -43,11 +36,12 @@ import com.ning.billing.catalog.VersionedCatalog;
import com.ning.billing.catalog.api.InvalidConfigException;
public class TestVersionedCatalogLoader {
+ private final VersionedCatalogLoader loader = new VersionedCatalogLoader();
@Test(enabled=true)
public void testPullContentsFrom() throws MalformedURLException, IOException {
- String contents = pullContentsFrom(new File("src/test/resources/WeaponsHireSmall.xml").toURI().toURL());
+ String contents = loader.pullContentsFrom(new File("src/test/resources/WeaponsHireSmall.xml").toURI().toURL());
assertTrue(contents.length() > 0);
@@ -56,10 +50,10 @@ public class TestVersionedCatalogLoader {
@Test(enabled=true)
public void testAppendToURL() throws MalformedURLException, IOException {
URL u1 = new URL("http://www.ning.com/foo");
- assertEquals("http://www.ning.com/foo/bar",appendToURL(u1, "bar").toString());
+ assertEquals("http://www.ning.com/foo/bar",loader.appendToURL(u1, "bar").toString());
URL u2 = new URL("http://www.ning.com/foo/");
- assertEquals("http://www.ning.com/foo/bar",appendToURL(u2, "bar").toString());
+ assertEquals("http://www.ning.com/foo/bar",loader.appendToURL(u2, "bar").toString());
}
@@ -72,7 +66,7 @@ public class TestVersionedCatalogLoader {
"replica.foo\n" +
"snv1/\n" +
"viking.xml\n" ;
- List<URL> urls = findXmlFileReferences(page, new URL("http://ning.com/"));
+ List<URL> urls = loader.findXmlFileReferences(page, new URL("http://ning.com/"));
assertEquals(2, urls.size());
assertEquals("http://ning.com/dg.xml", urls.get(0).toString());
assertEquals("http://ning.com/viking.xml", urls.get(1).toString());
@@ -98,7 +92,7 @@ public class TestVersionedCatalogLoader {
"</ul>" +
"<address>Apache/2.2.3 (CentOS) Server at <a href=\"mailto:kate@ning.com\">gepo.ningops.net</a> Port 80</address>" +
"</body></html>" ;
- List<String> hrefs = extractHrefs(page);
+ List<String> hrefs = loader.extractHrefs(page);
assertEquals(8, hrefs.size());
assertEquals("/config/trunk/", hrefs.get(0));
assertEquals("dg.xml", hrefs.get(1));
@@ -123,7 +117,7 @@ public class TestVersionedCatalogLoader {
"</ul>" +
"<address>Apache/2.2.3 (CentOS) Server at <a href=\"mailto:kate@ning.com\">gepo.ningops.net</a> Port 80</address>" +
"</body></html>" ;
- List<URL> urls = findXmlUrlReferences(page, new URL("http://ning.com/"));
+ List<URL> urls = loader.findXmlUrlReferences(page, new URL("http://ning.com/"));
assertEquals(2, urls.size());
assertEquals("http://ning.com/dg.xml", urls.get(0).toString());
assertEquals("http://ning.com/viking.xml", urls.get(1).toString());
@@ -132,7 +126,7 @@ public class TestVersionedCatalogLoader {
@Test(enabled=true)
public void testLoad() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException {
- VersionedCatalog c = load(new File("src/test/resources/versionedCatalog").toURI().toURL());
+ VersionedCatalog c = loader.load(new File("src/test/resources/versionedCatalog").toURI().toURL());
assertEquals(4, c.size());
Iterator<Catalog> it = c.iterator();
it.next(); //discard the baseline
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
new file mode 100644
index 0000000..c2add84
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/io/TestXMLReader.java
@@ -0,0 +1,38 @@
+/*
+ * 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.io;
+
+import java.io.File;
+import java.io.IOException;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.transform.TransformerException;
+
+import org.testng.annotations.Test;
+import org.xml.sax.SAXException;
+
+import com.ning.billing.catalog.api.InvalidConfigException;
+
+public class TestXMLReader {
+
+ @Test(enabled=true)
+ public void testCatalogLoad() throws IOException, TransformerException, JAXBException, SAXException, InvalidConfigException {
+ XMLReader.getCatalogFromName(new File("src/test/resources/WeaponsHire.xml").toURI().toURL());
+ XMLReader.getCatalogFromName(new File("src/test/resources/WeaponsHireSmall.xml").toURI().toURL());
+ }
+
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java b/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
new file mode 100644
index 0000000..07a9b79
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/MockCatalog.java
@@ -0,0 +1,89 @@
+/*
+ * 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 com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.ProductCategory;
+
+public class MockCatalog extends Catalog {
+ private static final String[] PRODUCT_NAMES = new String[]{ "TestProduct1", "TestProduct2", "TestProduct3"};
+
+ public MockCatalog() {
+ populateProducts();
+ populateRules();
+ populateProductTiers();
+ populatePlans();
+ populatePriceLists();
+ }
+
+ public void populateRules(){
+ setPlanRules(new PlanRules());
+ }
+
+ public void setRules(PlanPolicyChangeRule[] rules,
+ CaseChangePlanPolicy[] caseChangePlanPolicy,
+ CaseChangePlanAlignment[] caseChangePlanAlignment,
+ CaseCancelPolicy[] caseCancelPolicy,
+ CaseCreateAlignment[] caseCreateAlignment
+ ){
+
+ }
+
+ public void populateProducts() {
+ String[] names = getProductNames();
+ Product[] products = new Product[names.length];
+ for(int i = 0; i < names.length; i++) {
+ products[i] = new Product(names[i], ProductCategory.BASE);
+ }
+ setProducts(products);
+ }
+
+ public void populateProductTiers() {
+ //default to having a single tier with all products in it
+ ProductTier tier = new ProductTier();
+ tier.setProducts(getProducts());
+ getPlanRules().setProductTiers(new ProductTier[]{tier});
+ }
+
+ public void populatePlans() {
+ Product[] products = getProducts();
+ Plan[] plans = new Plan[products.length];
+ for(int i = 0; i < products.length; i++) {
+ plans[i] = new Plan(products[i].getName().toLowerCase() + "-plan",products[i],
+ new PlanPhase(BillingPeriod.MONTHLY, PhaseType.EVERGREEN));
+ }
+ setPlans(plans);
+ }
+
+ public void populatePriceLists() {
+ Plan[] plans = getPlans();
+ PriceList[] priceList = new PriceList[plans.length];
+ for(int i = 0; i < plans.length; i++) {
+ priceList[i] = new PriceList();
+ priceList[i].setName(plans[i].getName()+ "-pl");
+ priceList[i].setPlans(new Plan[]{plans[i]});
+ }
+ setPriceLists(priceList);
+ }
+
+ public String[] getProductNames() {
+ return PRODUCT_NAMES;
+ }
+
+
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestCase.java b/catalog/src/test/java/com/ning/billing/catalog/TestCase.java
new file mode 100644
index 0000000..5848c57
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestCase.java
@@ -0,0 +1,174 @@
+/*
+ * 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 static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
+
+import javax.xml.bind.annotation.XmlElement;
+
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PlanSpecifier;
+import com.ning.billing.catalog.api.ProductCategory;
+
+public class TestCase {
+ protected enum Result {
+ FOO, BAR, WIBBLE
+ }
+ protected class CaseResult extends Case<Result> {
+
+ @XmlElement(required=true)
+ private Result policy;
+
+ public CaseResult(Product product, ProductCategory productCategory, BillingPeriod billingPeriod, PriceList priceList,
+ Result policy) {
+ super(product, productCategory, billingPeriod, priceList, policy);
+ this.policy = policy;
+ }
+
+ @Override
+ protected Result getResult() {
+ return policy;
+ }
+ }
+
+ @Test(enabled=true)
+ public void testBasic(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product = cat.getProducts()[0];
+ PriceList priceList = cat.getPriceLists()[0];
+
+
+ CaseResult cr = new CaseResult(
+ product,
+ ProductCategory.BASE,
+ BillingPeriod.MONTHLY,
+ priceList,
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, "lala", ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildCardProduct(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product = cat.getProducts()[0];
+ PriceList priceList = cat.getPriceLists()[0];
+
+
+ CaseResult cr = new CaseResult(
+ null,
+ ProductCategory.BASE,
+ BillingPeriod.MONTHLY,
+ priceList,
+
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertion(Result.FOO, cr,"lala", ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildCardProductCategory(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product = cat.getProducts()[0];
+ PriceList priceList = cat.getPriceLists()[0];
+
+
+ CaseResult cr = new CaseResult(
+ product,
+ null,
+ BillingPeriod.MONTHLY,
+ priceList,
+
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, "lala", ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildCardBillingPeriod(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product = cat.getProducts()[0];
+ PriceList priceList = cat.getPriceLists()[0];
+
+
+ CaseResult cr = new CaseResult(
+ product,
+ ProductCategory.BASE,
+ null,
+ priceList,
+
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, "lala", ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertion(Result.FOO,cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildCardPriceList(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product = cat.getProducts()[0];
+ PriceList priceList = cat.getPriceLists()[0];
+
+
+ CaseResult cr = new CaseResult(
+ product,
+ ProductCategory.BASE,
+ BillingPeriod.MONTHLY,
+ null,
+
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, "lala", ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), cat);
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", cat);
+ }
+
+ protected void assertionNull(CaseResult cr, String productName, ProductCategory productCategory, BillingPeriod bp, String priceListName, Catalog cat){
+ assertNull(cr.getResult(new PlanSpecifier(productName, productCategory, bp, priceListName), cat));
+ }
+
+ protected void assertion(Result result, CaseResult cr, String productName, ProductCategory productCategory, BillingPeriod bp, String priceListName,Catalog cat){
+ assertEquals(result, cr.getResult(new PlanSpecifier(productName, productCategory, bp, priceListName), cat));
+ }
+
+
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestCaseChange.java b/catalog/src/test/java/com/ning/billing/catalog/TestCaseChange.java
new file mode 100644
index 0000000..ed2972d
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestCaseChange.java
@@ -0,0 +1,977 @@
+/*
+ * 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 static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
+
+import javax.xml.bind.annotation.XmlElement;
+
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+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;
+
+public class TestCaseChange {
+ protected enum Result {
+ FOO, BAR, WIBBLE
+ }
+
+ protected class CaseChangeResult extends CaseChange<Result> {
+
+ @XmlElement(required=true)
+ private Result result;
+
+ public CaseChangeResult(Product from, Product to,
+ ProductCategory fromProductCategory, ProductCategory toProductCategory,
+ BillingPeriod fromBP, BillingPeriod toBP,
+ PriceList fromPriceList, PriceList toPriceList,
+ PhaseType fromType,
+ Result result) {
+ super(from, to,
+ fromProductCategory, toProductCategory,
+ fromBP, toBP,
+ fromPriceList, toPriceList,
+ fromType,
+ result);
+ this.result = result;
+ }
+
+ @Override
+ protected Result getResult() {
+ return result;
+ }
+ }
+ @Test(enabled=true)
+ public void testBasic(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product1 = cat.getProducts()[0];
+ PriceList priceList1 = cat.getPriceLists()[0];
+
+ Product product2 = cat.getProducts()[2];
+ PriceList priceList2 = cat.getPriceLists()[2];
+
+
+ CaseChangeResult cr = new CaseChangeResult(
+ product1, product2,
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1,priceList2,
+ PhaseType.EVERGREEN,
+ Result.FOO);
+
+ assertion(Result.FOO, cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ "wrong", product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), "wrong",
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.ADD_ON, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.ADD_ON,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.ANNUAL, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.ANNUAL,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ "wrong", priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), "wrong",
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.TRIAL, cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildcardFromProduct(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product1 = cat.getProducts()[0];
+ PriceList priceList1 = cat.getPriceLists()[0];
+
+ Product product2 = cat.getProducts()[2];
+ PriceList priceList2 = cat.getPriceLists()[2];
+
+
+ CaseChangeResult cr = new CaseChangeResult(
+ null, product2,
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1,priceList2,
+ PhaseType.EVERGREEN,
+ Result.FOO);
+
+ assertion(Result.FOO, cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertion(Result.FOO,cr,
+ "wrong", product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.ADD_ON, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.ADD_ON,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), "wrong",
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.ANNUAL, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.ANNUAL,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ "wrong", priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), "wrong",
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.TRIAL, cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildcardToProduct(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product1 = cat.getProducts()[0];
+ PriceList priceList1 = cat.getPriceLists()[0];
+
+ Product product2 = cat.getProducts()[2];
+ PriceList priceList2 = cat.getPriceLists()[2];
+
+
+ CaseChangeResult cr = new CaseChangeResult(
+ product1, null,
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1,priceList2,
+ PhaseType.EVERGREEN,
+ Result.FOO);
+
+ assertion(Result.FOO, cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ "wrong", product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.ADD_ON, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.ADD_ON,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertion(Result.FOO, cr,
+ product1.getName(), "wrong",
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.ANNUAL, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.ANNUAL,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ "wrong", priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), "wrong",
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.TRIAL, cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildcardFromProductCategory(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product1 = cat.getProducts()[0];
+ PriceList priceList1 = cat.getPriceLists()[0];
+
+ Product product2 = cat.getProducts()[2];
+ PriceList priceList2 = cat.getPriceLists()[2];
+
+
+ CaseChangeResult cr = new CaseChangeResult(
+ product1, product2,
+ null, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1,priceList2,
+ PhaseType.EVERGREEN,
+ Result.FOO);
+
+ assertion(Result.FOO, cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ "wrong", product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), "wrong",
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertion(Result.FOO, cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.ADD_ON, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.ADD_ON,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.ANNUAL, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.ANNUAL,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ "wrong", priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), "wrong",
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.TRIAL, cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildcardToProductCategory(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product1 = cat.getProducts()[0];
+ PriceList priceList1 = cat.getPriceLists()[0];
+
+ Product product2 = cat.getProducts()[2];
+ PriceList priceList2 = cat.getPriceLists()[2];
+
+
+ CaseChangeResult cr = new CaseChangeResult(
+ product1, product2,
+ ProductCategory.BASE, null,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1,priceList2,
+ PhaseType.EVERGREEN,
+ Result.FOO);
+
+ assertion(Result.FOO, cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ "wrong", product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), "wrong",
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.ADD_ON, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertion(Result.FOO, cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.ADD_ON,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.ANNUAL, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.ANNUAL,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ "wrong", priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), "wrong",
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.TRIAL, cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildcardFromBillingPeriod(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product1 = cat.getProducts()[0];
+ PriceList priceList1 = cat.getPriceLists()[0];
+
+ Product product2 = cat.getProducts()[2];
+ PriceList priceList2 = cat.getPriceLists()[2];
+
+
+ CaseChangeResult cr = new CaseChangeResult(
+ product1, product2,
+ ProductCategory.BASE, ProductCategory.BASE,
+ null, BillingPeriod.MONTHLY,
+ priceList1, priceList2,
+ PhaseType.EVERGREEN,
+ Result.FOO);
+
+ assertion(Result.FOO, cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ "wrong", product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.ADD_ON, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.ADD_ON,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), "wrong",
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertion(Result.FOO,cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.ANNUAL, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.ANNUAL,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ "wrong", priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), "wrong",
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.TRIAL, cat);
+ }
+
+
+ @Test(enabled=true)
+ public void testWildCardToBillingPeriod(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product1 = cat.getProducts()[0];
+ PriceList priceList1 = cat.getPriceLists()[0];
+
+ Product product2 = cat.getProducts()[2];
+ PriceList priceList2 = cat.getPriceLists()[2];
+
+
+ CaseChangeResult cr = new CaseChangeResult(
+ product1, product2,
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, null,
+ priceList1,priceList2,
+ PhaseType.EVERGREEN,
+ Result.FOO);
+
+ assertion(Result.FOO, cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ "wrong", product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.ADD_ON, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.ADD_ON,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), "wrong",
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.ANNUAL, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertion(Result.FOO,cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.ANNUAL,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ "wrong", priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), "wrong",
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.TRIAL, cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildCardFromPriceList(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product1 = cat.getProducts()[0];
+ PriceList priceList1 = cat.getPriceLists()[0];
+
+ Product product2 = cat.getProducts()[2];
+ PriceList priceList2 = cat.getPriceLists()[2];
+
+
+ CaseChangeResult cr = new CaseChangeResult(
+ product1, product2,
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ null,priceList2,
+ PhaseType.EVERGREEN,
+ Result.FOO);
+
+ assertion(Result.FOO, cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ "wrong", product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.ADD_ON, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.ADD_ON,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), "wrong",
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.ANNUAL, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.ANNUAL,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertion(Result.FOO,cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ "wrong", priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), "wrong",
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.TRIAL, cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildcardToPriceList(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product1 = cat.getProducts()[0];
+ PriceList priceList1 = cat.getPriceLists()[0];
+
+ Product product2 = cat.getProducts()[2];
+ PriceList priceList2 = cat.getPriceLists()[2];
+
+
+ CaseChangeResult cr = new CaseChangeResult(
+ product1, product2,
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1,null,
+ PhaseType.EVERGREEN,
+ Result.FOO);
+
+ assertion(Result.FOO, cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ "wrong", product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.ADD_ON, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.ADD_ON,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), "wrong",
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.ANNUAL, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.ANNUAL,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ "wrong", priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertion(Result.FOO,cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), "wrong",
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.TRIAL, cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildcardPlanPhase(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product1 = cat.getProducts()[0];
+ PriceList priceList1 = cat.getPriceLists()[0];
+
+ Product product2 = cat.getProducts()[2];
+ PriceList priceList2 = cat.getPriceLists()[2];
+
+
+ CaseChangeResult cr = new CaseChangeResult(
+ product1, product2,
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1,priceList2,
+ null,
+ Result.FOO);
+
+ assertion(Result.FOO, cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ "wrong", product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.ADD_ON, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull( cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.ADD_ON,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), "wrong",
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.ANNUAL, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.ANNUAL,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ "wrong", priceList2.getName(),
+ PhaseType.EVERGREEN, cat);
+
+ assertionNull(cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), "wrong",
+ PhaseType.EVERGREEN, cat);
+
+ assertion(Result.FOO,cr,
+ product1.getName(), product2.getName(),
+ ProductCategory.BASE, ProductCategory.BASE,
+ BillingPeriod.MONTHLY, BillingPeriod.MONTHLY,
+ priceList1.getName(), priceList2.getName(),
+ PhaseType.TRIAL, cat);
+ }
+
+
+ protected void assertionNull(CaseChangeResult cr,
+ String fromProductName, String toProductName,
+ ProductCategory fromProductCategory, ProductCategory toProductCategory,
+ BillingPeriod fromBp, BillingPeriod toBp,
+ String fromPriceListName, String toPriceListName,
+ PhaseType phaseType, Catalog cat){
+ assertNull(cr.getResult(new PlanPhaseSpecifier(fromProductName, fromProductCategory, fromBp, fromPriceListName, phaseType),
+ new PlanSpecifier(toProductName, toProductCategory, toBp, toPriceListName),cat));
+ }
+
+ protected void assertion(Result result, CaseChangeResult cr,
+ String fromProductName, String toProductName,
+ ProductCategory fromProductCategory, ProductCategory toProductCategory,
+ BillingPeriod fromBp, BillingPeriod toBp,
+ String fromPriceListName, String toPriceListName,
+ PhaseType phaseType, Catalog cat){
+ assertEquals(result, cr.getResult(new PlanPhaseSpecifier(fromProductName, fromProductCategory,fromBp, fromPriceListName, phaseType),
+ new PlanSpecifier(toProductName, toProductCategory, toBp, toPriceListName),cat));
+ }
+
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestCasePhase.java b/catalog/src/test/java/com/ning/billing/catalog/TestCasePhase.java
new file mode 100644
index 0000000..9d3f7cc
--- /dev/null
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestCasePhase.java
@@ -0,0 +1,205 @@
+/*
+ * 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 static org.testng.AssertJUnit.assertEquals;
+import static org.testng.AssertJUnit.assertNull;
+
+import javax.xml.bind.annotation.XmlElement;
+
+import org.testng.annotations.Test;
+
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.PhaseType;
+import com.ning.billing.catalog.api.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.ProductCategory;
+
+public class TestCasePhase {
+ protected enum Result {
+ FOO, BAR, WIBBLE
+ }
+ protected class CaseResult extends CasePhase<Result> {
+
+ @XmlElement(required=true)
+ private Result policy;
+
+ public CaseResult(Product product, ProductCategory productCategory, BillingPeriod billingPeriod, PriceList priceList,
+ PhaseType phaseType, Result policy) {
+ super(product, productCategory, billingPeriod, priceList, phaseType, policy);
+ this.policy = policy;
+ }
+
+ @Override
+ protected Result getResult() {
+ return policy;
+ }
+ }
+
+ @Test(enabled=true)
+ public void testBasic(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product = cat.getProducts()[0];
+ PriceList priceList = cat.getPriceLists()[0];
+
+
+ CaseResult cr = new CaseResult(
+ product,
+ ProductCategory.BASE,
+ BillingPeriod.MONTHLY,
+ priceList,
+ PhaseType.EVERGREEN,
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, "lala", ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.TRIAL, cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildCardProduct(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product = cat.getProducts()[0];
+ PriceList priceList = cat.getPriceLists()[0];
+
+
+ CaseResult cr = new CaseResult(
+ null,
+ ProductCategory.BASE,
+ BillingPeriod.MONTHLY,
+ priceList,
+ PhaseType.EVERGREEN,
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertion(Result.FOO, cr,"lala", ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.TRIAL, cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildCardProductCategory(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product = cat.getProducts()[0];
+ PriceList priceList = cat.getPriceLists()[0];
+
+
+ CaseResult cr = new CaseResult(
+ product,
+ null,
+ BillingPeriod.MONTHLY,
+ priceList,
+ PhaseType.EVERGREEN,
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, "lala", ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.TRIAL, cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildCardBillingPeriod(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product = cat.getProducts()[0];
+ PriceList priceList = cat.getPriceLists()[0];
+
+
+ CaseResult cr = new CaseResult(
+ product,
+ ProductCategory.BASE,
+ null,
+ priceList,
+ PhaseType.EVERGREEN,
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, "lala", ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertion(Result.FOO,cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.TRIAL, cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildCardPriceList(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product = cat.getProducts()[0];
+ PriceList priceList = cat.getPriceLists()[0];
+
+
+ CaseResult cr = new CaseResult(
+ product,
+ ProductCategory.BASE,
+ BillingPeriod.MONTHLY,
+ null,
+ PhaseType.EVERGREEN,
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, "lala", ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.TRIAL, cat);
+ }
+
+ @Test(enabled=true)
+ public void testWildCardPhaseType(){
+ MockCatalog cat = new MockCatalog();
+
+ Product product = cat.getProducts()[0];
+ PriceList priceList = cat.getPriceLists()[0];
+
+
+ CaseResult cr = new CaseResult(
+ product,
+ ProductCategory.BASE,
+ BillingPeriod.MONTHLY,
+ priceList,
+ null,
+ Result.FOO);
+
+ assertion(Result.FOO, cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, "lala", ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.ADD_ON,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE,BillingPeriod.ANNUAL, priceList.getName(), PhaseType.EVERGREEN, cat);
+ assertionNull(cr, product.getName(), ProductCategory.BASE, BillingPeriod.MONTHLY, "dipsy", PhaseType.EVERGREEN, cat);
+ assertion(Result.FOO,cr, product.getName(), ProductCategory.BASE,BillingPeriod.MONTHLY, priceList.getName(), PhaseType.TRIAL, cat);
+ }
+
+ protected void assertionNull(CaseResult cr, String productName, ProductCategory productCategory, BillingPeriod bp, String priceListName, PhaseType phaseType, Catalog cat){
+ assertNull(cr.getResult(new PlanPhaseSpecifier(productName, productCategory, bp, priceListName, phaseType), cat));
+ }
+
+ protected void assertion(Result result, CaseResult cr, String productName, ProductCategory productCategory, BillingPeriod bp, String priceListName, PhaseType phaseType, Catalog cat){
+ assertEquals(result, cr.getResult(new PlanPhaseSpecifier(productName, productCategory, bp, priceListName, phaseType), cat));
+ }
+
+
+}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestPlanChangeRules.java b/catalog/src/test/java/com/ning/billing/catalog/TestPlanChangeRules.java
index ef0fe65..2ea4319 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestPlanChangeRules.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestPlanChangeRules.java
@@ -27,7 +27,7 @@ import static org.testng.AssertJUnit.assertNull;
import org.testng.annotations.Test;
-import com.ning.billing.catalog.PlanChangeRule.Qualifier;
+import com.ning.billing.catalog.PlanPolicyChangeRule.Qualifier;
import com.ning.billing.catalog.api.ActionPolicy;
import com.ning.billing.catalog.api.PhaseType;
import com.ning.billing.catalog.api.PlanPhaseSpecifier;
@@ -40,8 +40,8 @@ public class TestPlanChangeRules extends TestPlanRules {
Product P2 = createProduct("BP");
Catalog c = createCatalog(
- new PlanChangeRule[]{
- new PlanChangeRule(Qualifier.DEFAULT, ActionPolicy.END_OF_TERM, null)
+ new PlanPolicyChangeRule[]{
+ new PlanPolicyChangeRule(Qualifier.DEFAULT, ActionPolicy.END_OF_TERM, null)
},
null,
null,
@@ -49,8 +49,8 @@ public class TestPlanChangeRules extends TestPlanRules {
P2
);
assertEquals(ActionPolicy.END_OF_TERM,c.getPlanChangePolicy(
- new PlanPhaseSpecifier("FP", ANNUAL, null, EVERGREEN),
- new PlanPhaseSpecifier("BP", ANNUAL, null, EVERGREEN)
+ new PlanPhaseSpecifier("FP", null, ANNUAL, null, EVERGREEN),
+ new PlanPhaseSpecifier("BP", null, ANNUAL, null, EVERGREEN)
));
}
@@ -60,8 +60,8 @@ public class TestPlanChangeRules extends TestPlanRules {
Product P2 = createProduct("BP");
Catalog c = createCatalog(
- new PlanChangeRule[]{
- new PlanChangeRule(Qualifier.TERM_FROM_LONG_TO_SHORT, END_OF_TERM, null)
+ new PlanPolicyChangeRule[]{
+ new PlanPolicyChangeRule(Qualifier.TERM_FROM_LONG_TO_SHORT, END_OF_TERM, null)
},
null,
null,
@@ -70,13 +70,13 @@ public class TestPlanChangeRules extends TestPlanRules {
);
assertEquals(END_OF_TERM,c.getPlanChangePolicy(
- new PlanPhaseSpecifier("FP", ANNUAL, null, EVERGREEN),
- new PlanPhaseSpecifier("BP", MONTHLY, null, EVERGREEN)
+ new PlanPhaseSpecifier("FP", null, ANNUAL, null, EVERGREEN),
+ new PlanPhaseSpecifier("BP", null, MONTHLY, null, EVERGREEN)
));
assertNull(c.getPlanChangePolicy(
- new PlanPhaseSpecifier("FP", MONTHLY, null, EVERGREEN),
- new PlanPhaseSpecifier("BP", ANNUAL, null, EVERGREEN)
+ new PlanPhaseSpecifier("FP", null, MONTHLY, null, EVERGREEN),
+ new PlanPhaseSpecifier("BP", null, ANNUAL, null, EVERGREEN)
));
@@ -89,8 +89,8 @@ public class TestPlanChangeRules extends TestPlanRules {
Product P2 = createProduct("BP");
Catalog c = createCatalog(
- new PlanChangeRule[]{
- new PlanChangeRule(Qualifier.TERM_FROM_SHORT_TO_LONG, END_OF_TERM, null)
+ new PlanPolicyChangeRule[]{
+ new PlanPolicyChangeRule(Qualifier.TERM_FROM_SHORT_TO_LONG, END_OF_TERM, null)
},
null,
null,
@@ -99,13 +99,13 @@ public class TestPlanChangeRules extends TestPlanRules {
);
assertEquals(END_OF_TERM,c.getPlanChangePolicy(
- new PlanPhaseSpecifier("FP", MONTHLY, null, EVERGREEN),
- new PlanPhaseSpecifier("BP", ANNUAL, null, EVERGREEN)
+ new PlanPhaseSpecifier("FP", null, MONTHLY, null, EVERGREEN),
+ new PlanPhaseSpecifier("BP", null, ANNUAL, null, EVERGREEN)
));
assertNull(c.getPlanChangePolicy(
- new PlanPhaseSpecifier("FP", ANNUAL, null, EVERGREEN),
- new PlanPhaseSpecifier("BP", MONTHLY, null, EVERGREEN)
+ new PlanPhaseSpecifier("FP", null, ANNUAL, null, EVERGREEN),
+ new PlanPhaseSpecifier("BP", null, MONTHLY, null, EVERGREEN)
));
}
@@ -116,8 +116,8 @@ public class TestPlanChangeRules extends TestPlanRules {
Product P2 = createProduct("BP");
Catalog c = createCatalog(
- new PlanChangeRule[]{
- new PlanChangeRule(Qualifier.TERM_FROM_SHORT_TO_LONG, END_OF_TERM, PhaseType.EVERGREEN)
+ new PlanPolicyChangeRule[]{
+ new PlanPolicyChangeRule(Qualifier.TERM_FROM_SHORT_TO_LONG, END_OF_TERM, PhaseType.EVERGREEN)
},
null,
null,
@@ -126,13 +126,13 @@ public class TestPlanChangeRules extends TestPlanRules {
);
assertEquals(END_OF_TERM,c.getPlanChangePolicy(
- new PlanPhaseSpecifier("FP", MONTHLY, null, EVERGREEN),
- new PlanPhaseSpecifier("BP", ANNUAL, null, EVERGREEN)
+ new PlanPhaseSpecifier("FP", null, MONTHLY, null, EVERGREEN),
+ new PlanPhaseSpecifier("BP", null, ANNUAL, null, EVERGREEN)
));
assertNull(c.getPlanChangePolicy(
- new PlanPhaseSpecifier("FP", MONTHLY, null, TRIAL),
- new PlanPhaseSpecifier("BP", ANNUAL, null, TRIAL)
+ new PlanPhaseSpecifier("FP", null, MONTHLY, null, TRIAL),
+ new PlanPhaseSpecifier("BP", null, ANNUAL, null, TRIAL)
));
}
@@ -143,8 +143,8 @@ public class TestPlanChangeRules extends TestPlanRules {
Product P2 = createProduct("BP");
Catalog c = createCatalog(
- new PlanChangeRule[]{
- new PlanChangeRule(Qualifier.PRODUCT_FROM_LOW_TO_HIGH, IMMEDIATE, null)
+ new PlanPolicyChangeRule[]{
+ new PlanPolicyChangeRule(Qualifier.PRODUCT_FROM_LOW_TO_HIGH, IMMEDIATE, null)
},
null,
null,
@@ -153,13 +153,13 @@ public class TestPlanChangeRules extends TestPlanRules {
);
assertEquals(IMMEDIATE,c.getPlanChangePolicy(
- new PlanPhaseSpecifier("FP", MONTHLY, null, EVERGREEN),
- new PlanPhaseSpecifier("BP", ANNUAL, null, EVERGREEN)
+ new PlanPhaseSpecifier("FP", null, MONTHLY, null, EVERGREEN),
+ new PlanPhaseSpecifier("BP", null, ANNUAL, null, EVERGREEN)
));
assertNull(c.getPlanChangePolicy(
- new PlanPhaseSpecifier("BP", MONTHLY, null, EVERGREEN),
- new PlanPhaseSpecifier("FP", ANNUAL, null, EVERGREEN)
+ new PlanPhaseSpecifier("BP", null, MONTHLY, null, EVERGREEN),
+ new PlanPhaseSpecifier("FP", null, ANNUAL, null, EVERGREEN)
));
@@ -171,8 +171,8 @@ public class TestPlanChangeRules extends TestPlanRules {
Product P2 = createProduct("BP");
Catalog c = createCatalog(
- new PlanChangeRule[]{
- new PlanChangeRule(Qualifier.PRODUCT_FROM_HIGH_TO_LOW, IMMEDIATE, null)
+ new PlanPolicyChangeRule[]{
+ new PlanPolicyChangeRule(Qualifier.PRODUCT_FROM_HIGH_TO_LOW, IMMEDIATE, null)
},
null,
null,
@@ -181,13 +181,13 @@ public class TestPlanChangeRules extends TestPlanRules {
);
assertEquals(IMMEDIATE,c.getPlanChangePolicy(
- new PlanPhaseSpecifier("BP", ANNUAL, null, EVERGREEN),
- new PlanPhaseSpecifier("FP", MONTHLY, null, EVERGREEN)
+ new PlanPhaseSpecifier("BP", null, ANNUAL, null, EVERGREEN),
+ new PlanPhaseSpecifier("FP", null, MONTHLY, null, EVERGREEN)
));
assertNull(c.getPlanChangePolicy(
- new PlanPhaseSpecifier("FP", MONTHLY, null, TRIAL),
- new PlanPhaseSpecifier("BP", ANNUAL, null, TRIAL)
+ new PlanPhaseSpecifier("FP", null, MONTHLY, null, TRIAL),
+ new PlanPhaseSpecifier("BP", null, ANNUAL, null, TRIAL)
));
}
@@ -198,12 +198,12 @@ public class TestPlanChangeRules extends TestPlanRules {
Product P2 = createProduct("BP");
Catalog c = createCatalog(
- new PlanChangeRule[]{
- new PlanChangeRule(Qualifier.TERM_FROM_LONG_TO_SHORT, IMMEDIATE, null),
- new PlanChangeRule(Qualifier.PRODUCT_FROM_LOW_TO_HIGH, END_OF_TERM, null)
+ new PlanPolicyChangeRule[]{
+ new PlanPolicyChangeRule(Qualifier.TERM_FROM_LONG_TO_SHORT, IMMEDIATE, null),
+ new PlanPolicyChangeRule(Qualifier.PRODUCT_FROM_LOW_TO_HIGH, END_OF_TERM, null)
},
- new PlanChangeCase[] {
- new PlanChangeCase(P1, P2, MONTHLY, MONTHLY, null, null, null, null, null ),
+ new CaseChangePlanPolicy[] {
+ new CaseChangePlanPolicy(P1, P2, null, null, MONTHLY, MONTHLY, null, null, null, IMMEDIATE ),
},
null,
P1,
@@ -211,16 +211,42 @@ public class TestPlanChangeRules extends TestPlanRules {
);
assertEquals(END_OF_TERM,c.getPlanChangePolicy(
- new PlanPhaseSpecifier("FP", ANNUAL, null, EVERGREEN),
- new PlanPhaseSpecifier("BP", MONTHLY, null, EVERGREEN)
+ new PlanPhaseSpecifier("FP", null, ANNUAL, null, EVERGREEN),
+ new PlanPhaseSpecifier("BP", null, MONTHLY, null, EVERGREEN)
));
assertNull(c.getPlanChangePolicy(
- new PlanPhaseSpecifier("BP", MONTHLY, null, EVERGREEN),
- new PlanPhaseSpecifier("FP", ANNUAL, null, EVERGREEN)
+ new PlanPhaseSpecifier("BP", null, MONTHLY, null, EVERGREEN),
+ new PlanPhaseSpecifier("FP", null, ANNUAL, null, EVERGREEN)
));
}
+ @Test(enabled=true)
+ public void testPrecedenceSpecialCaseTrumpsRule() {
+ Product P1 = createProduct("FP");
+ Product P2 = createProduct("BP");
+ Catalog c = createCatalog(
+ new PlanPolicyChangeRule[]{
+ new PlanPolicyChangeRule(Qualifier.PRODUCT_FROM_LOW_TO_HIGH, END_OF_TERM, null)
+ },
+ new CaseChangePlanPolicy[] {
+ new CaseChangePlanPolicy(P1, P2, null, null, ANNUAL, MONTHLY, null, null, null, IMMEDIATE ),
+ },
+ null,
+ P1,
+ P2
+ );
+
+ assertEquals(IMMEDIATE,c.getPlanChangePolicy(
+ new PlanPhaseSpecifier("FP", null, ANNUAL, null, EVERGREEN),
+ new PlanPhaseSpecifier("BP", null, MONTHLY, null, EVERGREEN)
+ ));
+
+ assertNull(c.getPlanChangePolicy(
+ new PlanPhaseSpecifier("BP", null, MONTHLY, null, EVERGREEN),
+ new PlanPhaseSpecifier("FP", null, ANNUAL, null, EVERGREEN)
+ ));
+ }
}
diff --git a/catalog/src/test/java/com/ning/billing/catalog/TestPlanRules.java b/catalog/src/test/java/com/ning/billing/catalog/TestPlanRules.java
index 0f2ff50..6121a85 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestPlanRules.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestPlanRules.java
@@ -15,47 +15,54 @@
*/
package com.ning.billing.catalog;
+import com.ning.billing.catalog.api.ProductCategory;
+
public class TestPlanRules {
- public Catalog createCatalog(PlanChangeRule[] generalRules,
- PlanChangeCase[] specialCaseRules,
- PlanCancelCase[] cancelCaseRules,
+ public Catalog createCatalog(PlanPolicyChangeRule[] generalRules,
+ CaseChangePlanPolicy[] specialCaseRules,
+ CaseCancelPolicy[] cancelCaseRules,
Product fromP,
Product toP) {
Catalog c = new Catalog();
- PlanRules pcr = new PlanRules();
- pcr.setGeneralRules(generalRules);
- pcr.setSpecialCaseRules(specialCaseRules);
- pcr.setCancelCaseRules(cancelCaseRules);
+ PlanRules pcr = new PlanRules(
+ new ProductTier[] {new ProductTier(new Product[]{ fromP, toP })},
+ generalRules,
+ specialCaseRules,
+ cancelCaseRules,
+ null,
+ null
+ );
c.setPlanChangeRules(pcr);
- pcr.setProductTiers(new ProductTier[] {new ProductTier(new Product[]{ fromP, toP })});
c.setProducts(new Product[] { fromP, toP });
return c;
}
- public Catalog createCatalog(PlanChangeRule[] generalRules,
- PlanChangeCase[] specialCaseRules,
- PlanCancelCase[] cancelCaseRules,
- PlanAlignmentCase[] alignmentCases,
+ public Catalog createCatalog(PlanPolicyChangeRule[] generalRules,
+ CaseChangePlanPolicy[] specialCaseRules,
+ CaseCancelPolicy[] cancelCaseRules,
+ CaseChangePlanAlignment[] alignmentChangeCases,
Product fromP,
Product toP) {
Catalog c = new Catalog();
- PlanRules pcr = new PlanRules();
- pcr.setGeneralRules(generalRules);
- pcr.setSpecialCaseRules(specialCaseRules);
- pcr.setCancelCaseRules(cancelCaseRules);
- pcr.setAlignmentCase(alignmentCases);
+ PlanRules pcr = new PlanRules(
+ new ProductTier[] {new ProductTier(new Product[]{ fromP, toP })},
+ generalRules,
+ specialCaseRules,
+ cancelCaseRules,
+ alignmentChangeCases,
+ null
+ );
+
c.setPlanChangeRules(pcr);
- pcr.setProductTiers(new ProductTier[] {new ProductTier(new Product[]{ fromP, toP })});
c.setProducts(new Product[] { fromP, toP });
return c;
}
public Product createProduct(String name) {
- ProductType type = new ProductType("TestType");
- return new Product(type, name);
+ return new Product(name, ProductCategory.BASE);
}
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 a4d211c..a9a9cca 100644
--- a/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
+++ b/catalog/src/test/java/com/ning/billing/catalog/TestVersionedCatalog.java
@@ -30,36 +30,39 @@ 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.catalog.io.ICatalogLoader;
import com.ning.billing.catalog.io.VersionedCatalogLoader;
public class TestVersionedCatalog {
+ private final ICatalogLoader loader = new VersionedCatalogLoader();
+
@Test(enabled=true)
public void testAddCatalog() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException {
- VersionedCatalog vc = VersionedCatalogLoader.load(new File("src/test/resources/versionedCatalog").toURI().toURL());
+ VersionedCatalog vc = loader.load(new File("src/test/resources/versionedCatalog").toURI().toURL());
vc.add(new Catalog(new Date()));
assertEquals(5, vc.size());
}
@Test(enabled=true)
public void testApplyEffectiveDate() throws MalformedURLException, IOException, SAXException, InvalidConfigException, JAXBException {
- VersionedCatalog vc = VersionedCatalogLoader.load(new File("src/test/resources/versionedCatalog").toURI().toURL());
+ VersionedCatalog vc = loader.load(new File("src/test/resources/versionedCatalog").toURI().toURL());
Date d = new Date(1L);
- vc.applyEffectiveDate(d);
+ vc.configureEffectiveDate(d);
assertEquals(new Date(0), vc.getEffectiveDate()); // Start at the begining of time
DateTime dt = new DateTime("2011-01-01T00:00:00+00:00");
d = new Date(dt.getMillis() + 1000);
- vc.applyEffectiveDate(d);
+ vc.configureEffectiveDate(d);
assertEquals(dt.toDate(),vc.getEffectiveDate());
dt = new DateTime("2011-02-02T00:00:00+00:00");
d = new Date(dt.getMillis() + 1000);
- vc.applyEffectiveDate(d);
+ vc.configureEffectiveDate(d);
assertEquals(dt.toDate(),vc.getEffectiveDate());
dt = new DateTime("2011-03-03T00:00:00+00:00");
d = new Date(dt.getMillis() + 1000);
- vc.applyEffectiveDate(d);
+ vc.configureEffectiveDate(d);
assertEquals(dt.toDate(),vc.getEffectiveDate());
}
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
index ead1bb0..51e68dc 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-1.xml
@@ -19,28 +19,22 @@
xsi:noNamespaceSchemaLocation="../../../main/resources/CatalogSchema.xsd ">
<effectiveDate>2011-01-01T00:00:00+00:00</effectiveDate>
+ <catalogName>WeaponsHireSmall</catalogName>
<currencies>
<currency>USD</currency>
<currency>EUR</currency>
<currency>GBP</currency>
</currencies>
-
- <productTypes>
- <productType name="Firearms" />
- </productTypes>
<products>
<product name="Pistol">
- <type>Firearms</type>
<category>BASE</category>
</product>
<product name="Shotgun">
- <type>Firearms</type>
<category>BASE</category>
</product>
<product name="Laser-Scope">
- <type>Firearms</type>
<category>ADD_ON</category>
</product>
</products>
@@ -52,35 +46,35 @@
<product>Shotgun</product>
</tier>
</tiers>
- <changeRule>
+ <changePolicyRule>
<qualifier>DEFAULT</qualifier>
<policy>END_OF_TERM</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>TERM_FROM_SHORT_TO_LONG</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>PRODUCT_FROM_LOW_TO_HIGH</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>PRODUCT_FROM_LOW_TO_HIGH</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeCase>
+ </changePolicyRule>
+ <changePolicyCase>
<fromBillingPeriod>MONTHLY</fromBillingPeriod>
<toProduct>Shotgun</toProduct>
<toBillingPeriod>MONTHLY</toBillingPeriod>
<policy>END_OF_TERM</policy>
- </changeCase>
- <changeCase>
+ </changePolicyCase>
+ <changePolicyCase>
<phaseType>TRIAL</phaseType>
<policy>IMMEDIATE</policy>
- </changeCase>
- <alignmentCase>
+ </changePolicyCase>
+ <changeAlignmentCase>
<alignment>START_OF_SUBSCRIPTION</alignment>
- </alignmentCase>
+ </changeAlignmentCase>
</rules>
<plans>
@@ -107,7 +101,6 @@
<price><currency>USD</currency><value>29.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>ACCOUNT</billingAlignment>
</plan>
<plan name="shotgun-monthly">
<product>Shotgun</product>
@@ -133,7 +126,6 @@
<price><currency>GBP</currency><value>169.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>ACCOUNT</billingAlignment>
</plan>
<plan name="shotgun-annual">
<product>Shotgun</product>
@@ -158,7 +150,6 @@
<price><currency>GBP</currency><value>1699.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
</plans>
<priceLists>
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
index 8d32846..3ad25f3 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-2.xml
@@ -19,28 +19,22 @@
xsi:noNamespaceSchemaLocation="../../../main/resources/CatalogSchema.xsd ">
<effectiveDate>2011-02-02T00:00:00+00:00</effectiveDate>
+ <catalogName>WeaponsHireSmall</catalogName>
<currencies>
<currency>USD</currency>
<currency>EUR</currency>
<currency>GBP</currency>
</currencies>
-
- <productTypes>
- <productType name="Firearms" />
- </productTypes>
<products>
<product name="Pistol">
- <type>Firearms</type>
<category>BASE</category>
</product>
<product name="Shotgun">
- <type>Firearms</type>
<category>BASE</category>
</product>
<product name="Laser-Scope">
- <type>Firearms</type>
<category>ADD_ON</category>
</product>
</products>
@@ -52,38 +46,37 @@
<product>Shotgun</product>
</tier>
</tiers>
- <changeRule>
+ <changePolicyRule>
<qualifier>DEFAULT</qualifier>
<policy>END_OF_TERM</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>TERM_FROM_SHORT_TO_LONG</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>PRODUCT_FROM_LOW_TO_HIGH</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>PRODUCT_FROM_LOW_TO_HIGH</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeCase>
+ </changePolicyRule>
+ <changePolicyCase>
<fromBillingPeriod>MONTHLY</fromBillingPeriod>
<toProduct>Shotgun</toProduct>
<toBillingPeriod>MONTHLY</toBillingPeriod>
<policy>END_OF_TERM</policy>
- </changeCase>
- <changeCase>
+ </changePolicyCase>
+ <changePolicyCase>
<phaseType>TRIAL</phaseType>
<policy>IMMEDIATE</policy>
- </changeCase>
- <alignmentCase>
+ </changePolicyCase>
+ <changeAlignmentCase>
<alignment>START_OF_SUBSCRIPTION</alignment>
- </alignmentCase>
+ </changeAlignmentCase>
</rules>
-
<plans>
<plan name="pistol-monthly">
<product>Pistol</product>
@@ -108,7 +101,6 @@
<price><currency>USD</currency><value>29.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>ACCOUNT</billingAlignment>
</plan>
<plan name="shotgun-monthly">
<product>Shotgun</product>
@@ -134,7 +126,6 @@
<price><currency>GBP</currency><value>169.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>ACCOUNT</billingAlignment>
</plan>
<plan name="shotgun-annual">
<product>Shotgun</product>
@@ -159,7 +150,6 @@
<price><currency>GBP</currency><value>1699.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
</plans>
<priceLists>
diff --git a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
index e1c8bff..20ca041 100644
--- a/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
+++ b/catalog/src/test/resources/versionedCatalog/WeaponsHireSmall-3.xml
@@ -19,28 +19,22 @@
xsi:noNamespaceSchemaLocation="../../../main/resources/CatalogSchema.xsd ">
<effectiveDate>2011-03-03T00:00:00+00:00</effectiveDate>
+ <catalogName>WeaponsHireSmall</catalogName>
<currencies>
<currency>USD</currency>
<currency>EUR</currency>
<currency>GBP</currency>
</currencies>
-
- <productTypes>
- <productType name="Firearms" />
- </productTypes>
<products>
<product name="Pistol">
- <type>Firearms</type>
<category>BASE</category>
</product>
<product name="Shotgun">
- <type>Firearms</type>
<category>BASE</category>
</product>
<product name="Laser-Scope">
- <type>Firearms</type>
<category>ADD_ON</category>
</product>
</products>
@@ -52,35 +46,35 @@
<product>Shotgun</product>
</tier>
</tiers>
- <changeRule>
+ <changePolicyRule>
<qualifier>DEFAULT</qualifier>
<policy>END_OF_TERM</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>TERM_FROM_SHORT_TO_LONG</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>PRODUCT_FROM_LOW_TO_HIGH</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>PRODUCT_FROM_LOW_TO_HIGH</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeCase>
+ </changePolicyRule>
+ <changePolicyCase>
<fromBillingPeriod>MONTHLY</fromBillingPeriod>
<toProduct>Shotgun</toProduct>
<toBillingPeriod>MONTHLY</toBillingPeriod>
<policy>END_OF_TERM</policy>
- </changeCase>
- <changeCase>
+ </changePolicyCase>
+ <changePolicyCase>
<phaseType>TRIAL</phaseType>
<policy>IMMEDIATE</policy>
- </changeCase>
- <alignmentCase>
+ </changePolicyCase>
+ <changeAlignmentCase>
<alignment>START_OF_SUBSCRIPTION</alignment>
- </alignmentCase>
+ </changeAlignmentCase>
</rules>
<plans>
@@ -107,7 +101,6 @@
<price><currency>USD</currency><value>29.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>ACCOUNT</billingAlignment>
</plan>
<plan name="shotgun-monthly">
<product>Shotgun</product>
@@ -133,7 +126,6 @@
<price><currency>GBP</currency><value>169.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>ACCOUNT</billingAlignment>
</plan>
<plan name="shotgun-annual">
<product>Shotgun</product>
@@ -158,7 +150,6 @@
<price><currency>GBP</currency><value>1699.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
</plans>
<priceLists>
catalog/src/test/resources/WeaponsHire.xml 96(+40 -56)
diff --git a/catalog/src/test/resources/WeaponsHire.xml b/catalog/src/test/resources/WeaponsHire.xml
index 292879d..59b9093 100644
--- a/catalog/src/test/resources/WeaponsHire.xml
+++ b/catalog/src/test/resources/WeaponsHire.xml
@@ -40,6 +40,7 @@ Use Cases to do:
xsi:noNamespaceSchemaLocation="../../main/resources/CatalogSchema.xsd ">
<effectiveDate>2011-10-08T00:00:00+00:00</effectiveDate>
+ <catalogName>Firearms</catalogName>
<currencies>
<currency>USD</currency>
@@ -47,14 +48,8 @@ Use Cases to do:
<currency>GBP</currency>
</currencies>
- <productTypes>
- <productType name="Firearms" />
- <productType name="Blade" />
- </productTypes>
-
<products>
<product name="Pistol">
- <type>Firearms</type>
<category>BASE</category>
<available>
<addonProduct>Telescopic-Scope</addonProduct>
@@ -62,11 +57,9 @@ Use Cases to do:
</available>
</product>
<product name="Shotgun">
- <type>Firearms</type>
<category>BASE</category>
</product>
<product name="Assault-Rifle">
- <type>Firearms</type>
<category>BASE</category>
<included>
<addonProduct>Telescopic-Scope</addonProduct>
@@ -76,31 +69,24 @@ Use Cases to do:
</available>
</product>
<product name="Telescopic-Scope">
- <type>Firearms</type>
<category>ADD_ON</category>
</product>
<product name="Laser-Scope">
- <type>Firearms</type>
<category>ADD_ON</category>
</product>
<product name="Holster">
- <type>Firearms</type>
<category>ADD_ON</category>
</product>
<product name="Extra-Ammo">
- <type>Firearms</type>
<category>ADD_ON</category>
</product>
<product name="Refurbish-Maintenance">
- <type>Firearms</type>
<category>ADD_ON</category>
</product>
<product name="Bowie-Knife">
- <type>Blade</type>
<category>BASE</category>
</product>
<product name="Samuri-Sword">
- <type>Blade</type>
<category>BASE</category>
</product>
</products>
@@ -113,51 +99,65 @@ Use Cases to do:
<product>Assault-Rifle</product>
</tier>
</tiers>
- <changeRule>
+ <changePolicyRule>
<qualifier>DEFAULT</qualifier>
<policy>END_OF_TERM</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>TERM_FROM_SHORT_TO_LONG</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>PRODUCT_FROM_LOW_TO_HIGH</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeCase>
+ </changePolicyRule>
+ <changePolicyCase>
<fromBillingPeriod>MONTHLY</fromBillingPeriod>
<toProduct>Assault-Rifle</toProduct>
<toBillingPeriod>MONTHLY</toBillingPeriod>
<policy>END_OF_TERM</policy>
- </changeCase>
- <changeCase>
+ </changePolicyCase>
+ <changePolicyCase>
<toPriceList>rescue</toPriceList>
<policy>END_OF_TERM</policy>
- </changeCase>
- <changeCase>
- <phaseType>TRIAL</phaseType>
- <policy>IMMEDIATE</policy>
- </changeCase>
- <cancelCase>
- <policy>END_OF_TERM</policy>
- </cancelCase>
- <cancelCase>
+ </changePolicyCase>
+ <changePolicyCase>
<phaseType>TRIAL</phaseType>
<policy>IMMEDIATE</policy>
- </cancelCase>
- <alignmentCase>
+ </changePolicyCase>
+ <changeAlignmentCase>
<alignment>START_OF_SUBSCRIPTION</alignment>
- </alignmentCase>
- <alignmentCase>
+ </changeAlignmentCase>
+ <changeAlignmentCase>
<toPriceList>rescue</toPriceList>
<alignment>CHANGE_OF_PLAN</alignment>
- </alignmentCase>
- <alignmentCase>
+ </changeAlignmentCase>
+ <changeAlignmentCase>
<fromPriceList>rescue</fromPriceList>
<toPriceList>rescue</toPriceList>
<alignment>CHANGE_OF_PRICELIST</alignment>
- </alignmentCase>
+ </changeAlignmentCase>
+ <cancelPolicyCase>
+ <policy>END_OF_TERM</policy>
+ </cancelPolicyCase>
+ <cancelPolicyCase>
+ <phaseType>TRIAL</phaseType>
+ <policy>IMMEDIATE</policy>
+ </cancelPolicyCase>
+ <createAlignmentCase>
+ <alignment>START_OF_BUNDLE</alignment>
+ </createAlignmentCase>
+ <billingAlignmentCase>
+ <alignment>ACCOUNT</alignment>
+ </billingAlignmentCase>
+ <billingAlignmentCase>
+ <billingPeriod>ANNUAL</billingPeriod>
+ <alignment>SUBSCRIPTION</alignment>
+ </billingAlignmentCase>
+ <billingAlignmentCase>
+ <productCategory>ADD_ON</productCategory>
+ <alignment>BUNDLE</alignment>
+ </billingAlignmentCase>
</rules>
<plans>
@@ -184,7 +184,6 @@ Use Cases to do:
<price><currency>USD</currency><value>29.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>ACCOUNT</billingAlignment>
</plan>
<plan name="shotgun-monthly">
<product>Shotgun</product>
@@ -210,7 +209,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>169.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>ACCOUNT</billingAlignment>
</plan>
<plan name="assault-rifle-monthly">
<product>Assault-Rifle</product>
@@ -235,7 +233,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>399.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>ACCOUNT</billingAlignment>
</plan>
<plan name="pistol-annual">
<product>Pistol</product>
@@ -260,7 +257,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>199.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
<plan name="shotgun-annual">
<product>Shotgun</product>
@@ -285,7 +281,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>1699.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
<plan name="assault-rifle-annual">
<product>Assault-Rifle</product>
@@ -310,7 +305,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>3999.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
<plan name="pistol-annual-gunclub-discount">
<product>Pistol</product>
@@ -347,7 +341,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>199.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
<plan name="shotgun-annual-gunclub-discount">
<product>Shotgun</product>
@@ -384,7 +377,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>1699.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
<plan name="assault-rifle-annual-gunclub-discount">
<product>Assault-Rifle</product>
@@ -421,7 +413,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>3999.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
<plan name="laser-scope-monthly">
<product>Laser-Scope</product>
@@ -436,7 +427,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>1999.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>BUNDLE</billingAlignment>
</plan>
<plan name="telescopic-scope-monthly">
<product>Telescopic-Scope</product>
@@ -451,7 +441,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>999.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>BUNDLE</billingAlignment>
</plan>
<plan name="extra-ammo-monthly">
<product>Extra-Ammo</product>
@@ -466,7 +455,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>999.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>BUNDLE</billingAlignment>
<plansAllowedInBundle>-1</plansAllowedInBundle> <!-- arbitrary number of these (multipack) -->
</plan>
<plan name="holster-monthly-regular">
@@ -492,7 +480,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>199.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>BUNDLE</billingAlignment>
</plan>
<plan name="holster-monthly-special">
<product>Holster</product>
@@ -517,7 +504,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>199.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>BUNDLE</billingAlignment>
</plan>
<plan name="assault-rifle-annual-rescue">
<product>Assault-Rifle</product>
@@ -546,7 +532,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>3999.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
<plan name="refurbish-maintenance">
<product>Refurbish-Maintenance</product>
@@ -567,7 +552,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>599.95</value></price>
</fixedPrice>
</finalPhase>
- <billingAlignment>BUNDLE</billingAlignment>
</plan>
</plans>
<priceLists>
catalog/src/test/resources/WeaponsHireSmall.xml 39(+15 -24)
diff --git a/catalog/src/test/resources/WeaponsHireSmall.xml b/catalog/src/test/resources/WeaponsHireSmall.xml
index 9b8bbbc..a40f4c7 100644
--- a/catalog/src/test/resources/WeaponsHireSmall.xml
+++ b/catalog/src/test/resources/WeaponsHireSmall.xml
@@ -19,28 +19,22 @@
xsi:noNamespaceSchemaLocation="../../main/resources/CatalogSchema.xsd ">
<effectiveDate>2011-10-08T00:00:00+00:00</effectiveDate>
+ <catalogName>WeaponsHireSmall</catalogName>
<currencies>
<currency>USD</currency>
<currency>EUR</currency>
<currency>GBP</currency>
</currencies>
-
- <productTypes>
- <productType name="Firearms" />
- </productTypes>
<products>
<product name="Pistol">
- <type>Firearms</type>
<category>BASE</category>
</product>
<product name="Shotgun">
- <type>Firearms</type>
<category>BASE</category>
</product>
<product name="Laser-Scope">
- <type>Firearms</type>
<category>ADD_ON</category>
</product>
</products>
@@ -52,35 +46,35 @@
<product>Shotgun</product>
</tier>
</tiers>
- <changeRule>
+ <changePolicyRule>
<qualifier>DEFAULT</qualifier>
<policy>END_OF_TERM</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>TERM_FROM_SHORT_TO_LONG</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>PRODUCT_FROM_LOW_TO_HIGH</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>PRODUCT_FROM_LOW_TO_HIGH</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeCase>
+ </changePolicyRule>
+ <changePolicyCase>
<fromBillingPeriod>MONTHLY</fromBillingPeriod>
<toProduct>Shotgun</toProduct>
<toBillingPeriod>MONTHLY</toBillingPeriod>
<policy>END_OF_TERM</policy>
- </changeCase>
- <changeCase>
+ </changePolicyCase>
+ <changePolicyCase>
<phaseType>TRIAL</phaseType>
<policy>IMMEDIATE</policy>
- </changeCase>
- <alignmentCase>
+ </changePolicyCase>
+ <changeAlignmentCase>
<alignment>START_OF_SUBSCRIPTION</alignment>
- </alignmentCase>
+ </changeAlignmentCase>
</rules>
<plans>
@@ -107,7 +101,6 @@
<price><currency>USD</currency><value>29.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>ACCOUNT</billingAlignment>
</plan>
<plan name="shotgun-monthly">
<product>Shotgun</product>
@@ -133,7 +126,6 @@
<price><currency>GBP</currency><value>169.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>ACCOUNT</billingAlignment>
</plan>
<plan name="shotgun-annual">
<product>Shotgun</product>
@@ -158,7 +150,6 @@
<price><currency>GBP</currency><value>1699.95</value></price>
</recurringPrice>
</finalPhase>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
</plans>
<priceLists>
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/IPlanAligner.java b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/IPlanAligner.java
new file mode 100644
index 0000000..ff57cf1
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/IPlanAligner.java
@@ -0,0 +1,59 @@
+/*
+ * 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.entitlement.alignment;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.IPlan;
+import com.ning.billing.catalog.api.IPlanPhase;
+import com.ning.billing.entitlement.api.user.Subscription;
+
+public interface IPlanAligner {
+
+
+ public final static class TimedPhase {
+
+ private final IPlanPhase phase;
+ private final DateTime startPhase;
+
+ public TimedPhase(IPlanPhase phase, DateTime startPhase) {
+ super();
+ this.phase = phase;
+ this.startPhase = startPhase;
+ }
+
+ public IPlanPhase getPhase() {
+ return phase;
+ }
+
+ public DateTime getStartPhase() {
+ return startPhase;
+ }
+ }
+
+ public TimedPhase getCurrentTimedPhaseOnCreate(Subscription subscription, IPlan plan, String priceList, DateTime effectiveDate);
+
+ public TimedPhase getNextTimedPhaseOnCreate(Subscription subscription, IPlan plan, String priceList, DateTime effectiveDate);
+
+ public TimedPhase getCurrentTimedPhaseOnChange(Subscription subscription, IPlan plan, String priceList, DateTime effectiveDate);
+
+ public TimedPhase getNextTimedPhaseOnChange(Subscription subscription, IPlan plan, String priceList, DateTime effectiveDate);
+
+ public TimedPhase getNextTimedPhase(Subscription subscription, IPlan plan, DateTime effectiveDate, DateTime planStartDate);
+
+
+}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
new file mode 100644
index 0000000..7856dab
--- /dev/null
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/alignment/PlanAligner.java
@@ -0,0 +1,200 @@
+/*
+ * 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.entitlement.alignment;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.joda.time.DateTime;
+
+import com.ning.billing.catalog.api.ICatalog;
+import com.ning.billing.catalog.api.IDuration;
+import com.ning.billing.catalog.api.IPlan;
+import com.ning.billing.catalog.api.IPlanPhase;
+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.entitlement.api.user.Subscription;
+import com.ning.billing.entitlement.exceptions.EntitlementError;
+import com.ning.billing.util.clock.Clock;
+
+public class PlanAligner implements IPlanAligner {
+
+ // STEPH this is a bit broken right now until we figure out to retrieve ICatalog
+ private /*final*/ ICatalog catalog;
+
+ public PlanAligner() {
+ //this.catalog = Engine.getInstance().getCatalog();
+ }
+
+ public void init(ICatalog catalog) {
+ this.catalog = catalog;
+ }
+
+ private enum WhichPhase {
+ CURRENT,
+ NEXT
+ }
+
+ @Override
+ public TimedPhase getCurrentTimedPhaseOnCreate(Subscription subscription,
+ IPlan plan, String priceList, DateTime effectiveDate) {
+ return getTimedPhaseOnCreate(subscription, plan, priceList, effectiveDate, WhichPhase.CURRENT);
+ }
+
+ @Override
+ public TimedPhase getNextTimedPhaseOnCreate(Subscription subscription,
+ IPlan plan, String priceList, DateTime effectiveDate) {
+ return getTimedPhaseOnCreate(subscription, plan, priceList, effectiveDate, WhichPhase.NEXT);
+ }
+
+ @Override
+ public TimedPhase getCurrentTimedPhaseOnChange(Subscription subscription,
+ IPlan plan, String priceList, DateTime effectiveDate) {
+ return getTimedPhaseOnChange(subscription, plan, priceList, effectiveDate, WhichPhase.CURRENT);
+ }
+
+ @Override
+ public TimedPhase getNextTimedPhaseOnChange(Subscription subscription,
+ IPlan plan, String priceList, DateTime effectiveDate) {
+ return getTimedPhaseOnChange(subscription, plan, priceList, effectiveDate, WhichPhase.NEXT);
+ }
+
+
+
+ @Override
+ public TimedPhase getNextTimedPhase(Subscription subscription,
+ IPlan plan, DateTime effectiveDate, DateTime planStartDate) {
+ List<TimedPhase> timedPhases = getPhaseAlignments(subscription, plan, effectiveDate, planStartDate);
+ return getTimedPhase(timedPhases, effectiveDate, WhichPhase.NEXT);
+ }
+
+ private TimedPhase getTimedPhaseOnCreate(Subscription subscription,
+ IPlan plan, String priceList, DateTime effectiveDate, WhichPhase which) {
+
+ PlanSpecifier planSpecifier = new PlanSpecifier(plan.getProduct().getName(),
+ plan.getProduct().getCategory(),
+ plan.getBillingPeriod(),
+ priceList);
+
+ DateTime planStartDate = null;
+ PlanAlignmentCreate alignement = catalog.getPlanCreateAlignment(planSpecifier);
+ switch(alignement) {
+ case START_OF_SUBSCRIPTION:
+ planStartDate = subscription.getStartDate();
+ break;
+ case START_OF_BUNDLE:
+ planStartDate = subscription.getBundleStartDate();
+ break;
+ default:
+ throw new EntitlementError(String.format("Unknwon PlanAlignmentCreate %s", alignement));
+ }
+ List<TimedPhase> timedPhases = getPhaseAlignments(subscription, plan, effectiveDate, planStartDate);
+ return getTimedPhase(timedPhases, effectiveDate, which);
+ }
+
+ private TimedPhase getTimedPhaseOnChange(Subscription subscription,
+ IPlan plan, String priceList, DateTime effectiveDate, WhichPhase which) {
+
+ IPlanPhase currentPhase = subscription.getCurrentPhase();
+ IPlan currentPlan = subscription.getCurrentPlan();
+ String currentPriceList = subscription.getCurrentPriceList();
+
+ PlanPhaseSpecifier fromPlanPhaseSpecifier = new PlanPhaseSpecifier(currentPlan.getProduct().getName(),
+ currentPlan.getProduct().getCategory(),
+ currentPlan.getBillingPeriod(),
+ currentPriceList,
+ currentPhase.getPhaseType());
+
+ PlanSpecifier toPlanSpecifier = new PlanSpecifier(plan.getProduct().getName(),
+ plan.getProduct().getCategory(),
+ plan.getBillingPeriod(),
+ priceList);
+
+ DateTime planStartDate = null;
+ PlanAlignmentChange alignment = catalog.getPlanChangeAlignment(fromPlanPhaseSpecifier, toPlanSpecifier);
+ switch(alignment) {
+ case START_OF_SUBSCRIPTION:
+ planStartDate = subscription.getStartDate();
+ break;
+ case START_OF_BUNDLE:
+ planStartDate = subscription.getBundleStartDate();
+ break;
+ case CHANGE_OF_PLAN:
+ // STEPH
+ throw new EntitlementError(String.format("Not implemented yet %s", alignment));
+ //break;
+ case CHANGE_OF_PRICELIST:
+ // STEPH
+ throw new EntitlementError(String.format("Not implemented yet %s", alignment));
+ //break;
+ default:
+ throw new EntitlementError(String.format("Unknwon PlanAlignmentChange %s", alignment));
+ }
+ List<TimedPhase> timedPhases = getPhaseAlignments(subscription, plan, effectiveDate, planStartDate);
+ return getTimedPhase(timedPhases, effectiveDate, which);
+ }
+
+ private List<TimedPhase> getPhaseAlignments(Subscription subscription, IPlan plan,
+ DateTime effectiveDate, DateTime planStartDate) {
+
+ List<TimedPhase> result = new LinkedList<IPlanAligner.TimedPhase>();
+
+ DateTime curPhaseStart = planStartDate;
+ if (plan.getInitialPhases() == null) {
+ result.add(new TimedPhase(plan.getFinalPhase(), curPhaseStart));
+ return result;
+ }
+
+ DateTime nextPhaseStart = null;
+ for (IPlanPhase cur : plan.getInitialPhases()) {
+
+ result.add(new TimedPhase(cur, curPhaseStart));
+
+ IDuration curPhaseDuration = cur.getDuration();
+ nextPhaseStart = Clock.addDuration(curPhaseStart, curPhaseDuration);
+ if (nextPhaseStart == null) {
+ throw new EntitlementError(String.format("Unexpected non ending UNLIMITED phase for plan %s",
+ plan.getName()));
+ }
+ curPhaseStart = nextPhaseStart;
+ }
+ result.add(new TimedPhase(plan.getFinalPhase(), nextPhaseStart));
+ return result;
+ }
+
+ private TimedPhase getTimedPhase(List<TimedPhase> timedPhases, DateTime effectiveDate, WhichPhase which) {
+ TimedPhase cur = null;
+ TimedPhase next = null;
+ for (TimedPhase phase : timedPhases) {
+ if (phase.getStartPhase().isAfter(effectiveDate)) {
+ next = phase;
+ break;
+ }
+ cur = phase;
+ }
+ switch(which) {
+ case CURRENT:
+ return cur;
+ case NEXT:
+ return next;
+ default:
+ throw new EntitlementError(String.format("Unepected %s TimedPhase", which));
+ }
+ }
+}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
index 9e7e154..ebb180e 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/Subscription.java
@@ -33,14 +33,16 @@ 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.PlanPhaseSpecifier;
+import com.ning.billing.catalog.api.PlanSpecifier;
import com.ning.billing.catalog.api.ProductCategory;
-import com.ning.billing.entitlement.alignment.EntitlementAlignment;
-import com.ning.billing.entitlement.api.user.ISubscription.SubscriptionState;
+import com.ning.billing.entitlement.alignment.IPlanAligner;
+import com.ning.billing.entitlement.alignment.IPlanAligner.TimedPhase;
import com.ning.billing.entitlement.engine.core.Engine;
import com.ning.billing.entitlement.engine.dao.IEntitlementDao;
import com.ning.billing.entitlement.events.IEvent;
import com.ning.billing.entitlement.events.IEvent.EventType;
import com.ning.billing.entitlement.events.phase.IPhaseEvent;
+import com.ning.billing.entitlement.events.phase.PhaseEvent;
import com.ning.billing.entitlement.events.user.ApiEventCancel;
import com.ning.billing.entitlement.events.user.ApiEventChange;
import com.ning.billing.entitlement.events.user.ApiEventType;
@@ -61,6 +63,7 @@ public class Subscription extends PrivateFields implements ISubscription {
private final IClock clock;
private final IEntitlementDao dao;
private final ICatalog catalog;
+ private final IPlanAligner planAligner;
// STEPH interaction with billing /payment system
private final DateTime chargedThroughDate;
@@ -148,7 +151,7 @@ public class Subscription extends PrivateFields implements ISubscription {
this.clock = engine.getClock();
this.dao = engine.getDao();
this.catalog = engine.getCatalog();
-
+ this.planAligner = engine.getPlanAligner();
this.id = id;
this.bundleId = bundleId;
this.startDate = startDate;
@@ -218,8 +221,13 @@ public class Subscription extends PrivateFields implements ISubscription {
DateTime now = clock.getUTCNow();
- PlanPhaseSpecifier planPhase = new PlanPhaseSpecifier(getCurrentPlan().getProduct().getName(),
- getCurrentPlan().getBillingPeriod(), getCurrentPriceList(), getCurrentPhase().getPhaseType());
+ IPlan currentPlan = getCurrentPlan();
+ PlanPhaseSpecifier planPhase = new PlanPhaseSpecifier(currentPlan.getProduct().getName(),
+ currentPlan.getProduct().getCategory(),
+ getCurrentPlan().getBillingPeriod(),
+ getCurrentPriceList(),
+ getCurrentPhase().getPhaseType());
+
ActionPolicy policy = catalog.getPlanCancelPolicy(planPhase);
DateTime effectiveDate = getPlanChangeEffectiveDate(policy, now);
IEvent cancelEvent = new ApiEventCancel(id, bundleStartDate, now, now, effectiveDate, activeVersion);
@@ -237,10 +245,9 @@ public class Subscription extends PrivateFields implements ISubscription {
List<IEvent> uncancelEvents = new ArrayList<IEvent>();
uncancelEvents.add(uncancelEvent);
- // Recalculate Plan alignment for next phase event
- EntitlementAlignment planPhaseAlignment = new EntitlementAlignment(id, now, bundleStartDate, getCurrentPlan(),
- now, activeVersion);
- IPhaseEvent nextPhaseEvent = planPhaseAlignment.getNextPhaseEvent();
+ DateTime planStartDate = getCurrentPlanStart();
+ TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(this, getCurrentPlan(), now, planStartDate);
+ IPhaseEvent nextPhaseEvent = PhaseEvent.getNextPhaseEvent(nextTimedPhase, this, now);
if (nextPhaseEvent != null) {
uncancelEvents.add(nextPhaseEvent);
}
@@ -271,20 +278,25 @@ public class Subscription extends PrivateFields implements ISubscription {
productName, term.toString(), realPriceList);
}
- PlanPhaseSpecifier fromPlanPhase = new PlanPhaseSpecifier(getCurrentPlan().getProduct().getName(),
- getCurrentPlan().getBillingPeriod(),
+ IPlan currentPlan = getCurrentPlan();
+ PlanPhaseSpecifier fromPlanPhase = new PlanPhaseSpecifier(currentPlan.getProduct().getName(),
+ currentPlan.getProduct().getCategory(),
+ currentPlan.getBillingPeriod(),
currentPriceList, getCurrentPhase().getPhaseType());
- PlanPhaseSpecifier toPlanPhase = new PlanPhaseSpecifier(newPlan.getProduct().getName(),
+ PlanSpecifier toPlanPhase = new PlanSpecifier(newPlan.getProduct().getName(),
+ newPlan.getProduct().getCategory(),
newPlan.getBillingPeriod(),
- realPriceList, null);
+ realPriceList);
ActionPolicy policy = catalog.getPlanChangePolicy(fromPlanPhase, toPlanPhase);
DateTime effectiveDate = getPlanChangeEffectiveDate(policy, now);
- IEvent changeEvent = new ApiEventChange(id, bundleStartDate, now, newPlan, realPriceList, now, effectiveDate, activeVersion);
- EntitlementAlignment planPhaseAlignment = new EntitlementAlignment(id, now, bundleStartDate, newPlan,
- effectiveDate, activeVersion);
- IPhaseEvent nextPhaseEvent = planPhaseAlignment.getNextPhaseEvent();
+ TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnChange(this, newPlan, realPriceList, effectiveDate);
+ IEvent changeEvent = new ApiEventChange(id, bundleStartDate, now, newPlan.getName(), currentTimedPhase.getPhase().getName(),
+ realPriceList, now, effectiveDate, activeVersion);
+
+ TimedPhase nextTimedPhase = planAligner.getNextTimedPhaseOnChange(this, newPlan, realPriceList, effectiveDate);
+ IPhaseEvent nextPhaseEvent = PhaseEvent.getNextPhaseEvent(nextTimedPhase, this, now);
List<IEvent> changeEvents = new ArrayList<IEvent>();
// Add phase event first so we expect to see PHASE event first-- mostly for test expectation
if (nextPhaseEvent != null) {
@@ -341,6 +353,28 @@ public class Subscription extends PrivateFields implements ISubscription {
return paidThroughDate;
}
+ public DateTime getCurrentPlanStart() {
+
+ if (transitions == null) {
+ throw new EntitlementError(String.format("No transitions for subscription %s", getId()));
+ }
+
+ Iterator<SubscriptionTransition> it = ((LinkedList<SubscriptionTransition>) transitions).descendingIterator();
+ while (it.hasNext()) {
+ SubscriptionTransition cur = it.next();
+ if (cur.getTransitionTime().isAfter(clock.getUTCNow())) {
+ // Skip future events
+ continue;
+ }
+ if (cur.getEventType() == EventType.API_USER &&
+ cur.getApiEventType() == ApiEventType.CHANGE) {
+ return cur.getTransitionTime();
+ }
+ }
+ // CREATE event
+ return transitions.get(0).getTransitionTime();
+ }
+
public List<ISubscriptionTransition> getActiveTransitions() {
if (transitions == null) {
return null;
@@ -380,7 +414,7 @@ public class Subscription extends PrivateFields implements ISubscription {
for (SubscriptionTransition cur : transitions) {
if (cur.getTransitionTime().isBefore(clock.getUTCNow()) ||
cur.getEventType() == EventType.PHASE ||
- cur.getApiEventType() != ApiEventType.CHANGE) {
+ cur.getApiEventType() != ApiEventType.CHANGE) {
continue;
}
return true;
@@ -407,6 +441,7 @@ public class Subscription extends PrivateFields implements ISubscription {
return effectiveDate;
}
+
private DateTime getCurrentPhaseStart() {
if (transitions == null) {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/UserApi.java b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/UserApi.java
index a922486..bbf147f 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/api/user/UserApi.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/api/user/UserApi.java
@@ -29,8 +29,8 @@ import com.ning.billing.catalog.api.BillingPeriod;
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.entitlement.alignment.EntitlementAlignment;
-import com.ning.billing.entitlement.alignment.EntitlementAlignment.TimedPhase;
+import com.ning.billing.entitlement.alignment.IPlanAligner;
+import com.ning.billing.entitlement.alignment.IPlanAligner.TimedPhase;
import com.ning.billing.entitlement.api.user.IApiListener;
import com.ning.billing.entitlement.api.user.ISubscription;
import com.ning.billing.entitlement.api.user.ISubscriptionBundle;
@@ -50,13 +50,15 @@ public class UserApi implements IUserApi {
private final IClock clock;
private final IEntitlementDao dao;
private final ICatalog catalog;
+ private final IPlanAligner planAligner;
@Inject
- public UserApi(Engine engine, IClock clock, IEntitlementDao dao) {
+ public UserApi(Engine engine, IClock clock, IPlanAligner planAligner, IEntitlementDao dao) {
super();
this.engine = engine;
this.clock = clock;
this.dao = dao;
+ this.planAligner = planAligner;
this.catalog = engine.getCatalog();
}
@@ -139,14 +141,17 @@ public class UserApi implements IUserApi {
plan.getProduct().getCategory().toString()));
}
- Subscription subscription = new Subscription(bundleId, plan.getProduct().getCategory(), bundleStartDate, now);
+ DateTime effectiveDate = now;
+
+ Subscription subscription = new Subscription(bundleId, plan.getProduct().getCategory(), bundleStartDate, effectiveDate);
+
+ TimedPhase currentTimedPhase = planAligner.getCurrentTimedPhaseOnCreate(subscription, plan, realPriceList, effectiveDate);
ApiEventCreate creationEvent =
- new ApiEventCreate(subscription.getId(), bundleStartDate, now, plan, realPriceList,
- now, now, subscription.getActiveVersion());
+ new ApiEventCreate(subscription.getId(), bundleStartDate, now, plan.getName(), currentTimedPhase.getPhase().getName(), realPriceList,
+ now, effectiveDate, subscription.getActiveVersion());
- EntitlementAlignment planPhaseAlignment = new EntitlementAlignment(subscription.getId(), now,
- bundleStartDate, plan, now, subscription.getActiveVersion());
- IPhaseEvent nextPhaseEvent = planPhaseAlignment.getNextPhaseEvent();
+ TimedPhase nextTimedPhase = planAligner.getNextTimedPhaseOnCreate(subscription, plan, realPriceList, effectiveDate);
+ IPhaseEvent nextPhaseEvent = PhaseEvent.getNextPhaseEvent(nextTimedPhase, subscription, now);
List<IEvent> events = new ArrayList<IEvent>();
events.add(creationEvent);
if (nextPhaseEvent != null) {
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessor.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessor.java
index fdbaefb..437f21c 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessor.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessor.java
@@ -21,13 +21,13 @@ import java.util.List;
import com.google.inject.Inject;
import com.ning.billing.entitlement.engine.dao.IEntitlementDao;
import com.ning.billing.entitlement.events.IEvent;
-import com.ning.billing.entitlement.glue.IEngineConfig;
+import com.ning.billing.entitlement.glue.IEntitlementConfig;
import com.ning.billing.util.clock.IClock;
public class ApiEventProcessor extends ApiEventProcessorBase {
@Inject
- public ApiEventProcessor(IClock clock, IEntitlementDao dao, IEngineConfig config) {
+ public ApiEventProcessor(IClock clock, IEntitlementDao dao, IEntitlementConfig config) {
super(clock, dao, config);
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java
index c198226..b83b0be 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorBase.java
@@ -31,7 +31,7 @@ import org.slf4j.LoggerFactory;
import com.google.inject.Inject;
import com.ning.billing.entitlement.engine.dao.IEntitlementDao;
import com.ning.billing.entitlement.events.IEvent;
-import com.ning.billing.entitlement.glue.IEngineConfig;
+import com.ning.billing.entitlement.glue.IEntitlementConfig;
import com.ning.billing.util.clock.IClock;
public abstract class ApiEventProcessorBase implements IApiEventProcessor {
@@ -51,14 +51,14 @@ public abstract class ApiEventProcessorBase implements IApiEventProcessor {
protected final IClock clock;
private Executor executor;
- private final IEngineConfig config;
+ private final IEntitlementConfig config;
protected IEventListener listener;
protected long nbProcessedEvents;
protected volatile boolean isProcessingEvents;
@Inject
- public ApiEventProcessorBase(IClock clock, IEntitlementDao dao, IEngineConfig config) {
+ public ApiEventProcessorBase(IClock clock, IEntitlementDao dao, IEntitlementConfig config) {
this.clock = clock;
this.dao = dao;
this.config = config;
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
index 62bbae2..2511884 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/core/Engine.java
@@ -27,8 +27,10 @@ import com.google.inject.Inject;
import com.ning.billing.catalog.api.ICatalog;
import com.ning.billing.catalog.api.ICatalogUserApi;
import com.ning.billing.catalog.api.IPlan;
-import com.ning.billing.entitlement.alignment.EntitlementAlignment;
-import com.ning.billing.entitlement.alignment.EntitlementAlignment.TimedPhase;
+
+import com.ning.billing.entitlement.alignment.IPlanAligner;
+import com.ning.billing.entitlement.alignment.IPlanAligner.TimedPhase;
+import com.ning.billing.entitlement.alignment.PlanAligner;
import com.ning.billing.entitlement.api.user.IApiListener;
import com.ning.billing.entitlement.api.user.ISubscription;
import com.ning.billing.entitlement.api.user.Subscription;
@@ -39,7 +41,7 @@ import com.ning.billing.entitlement.events.phase.IPhaseEvent;
import com.ning.billing.entitlement.events.phase.PhaseEvent;
import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.entitlement.events.user.IUserEvent;
-import com.ning.billing.entitlement.glue.IEngineConfig;
+import com.ning.billing.entitlement.glue.IEntitlementConfig;
import com.ning.billing.util.clock.IClock;
public class Engine implements IEventListener {
@@ -52,19 +54,25 @@ public class Engine implements IEventListener {
private final IEntitlementDao dao;
private final IApiEventProcessor apiEventProcessor;
private final ICatalogUserApi catalogApi;
+ private final IPlanAligner planAligner;
private List<IApiListener> observers;
@Inject
- public Engine(IClock clock, IEntitlementDao dao, IApiEventProcessor apiEventProcessor, ICatalogUserApi catalogApi, IEngineConfig config) {
+ public Engine(IClock clock, IEntitlementDao dao, IApiEventProcessor apiEventProcessor, ICatalogUserApi catalogApi,
+ IPlanAligner planAligner, IEntitlementConfig config) {
super();
this.clock = clock;
this.catalogApi = catalogApi;
this.dao = dao;
this.apiEventProcessor = apiEventProcessor;
+ this.planAligner = planAligner;
this.catalog = readCatalogFromConfig(config.getCatalogConfigFileName());
this.observers = null;
instance = this;
+
+ // STEPH yack
+ ((PlanAligner) planAligner).init(catalog);
}
public void start() {
@@ -126,11 +134,8 @@ public class Engine implements IEventListener {
DateTime now = clock.getUTCNow();
-
- EntitlementAlignment planPhaseAlignment = new EntitlementAlignment(subscription.getId(),
- now, subscription.getBundleStartDate(), subscription.getCurrentPlan(),
- subscription.getLatestTranstion().getTransitionTime(), subscription.getActiveVersion());
- IPhaseEvent nextPhaseEvent = planPhaseAlignment.getNextPhaseEvent();
+ TimedPhase nextTimedPhase = planAligner.getNextTimedPhase(subscription, subscription.getCurrentPlan(), now, subscription.getCurrentPlanStart());
+ IPhaseEvent nextPhaseEvent = PhaseEvent.getNextPhaseEvent(nextTimedPhase, subscription, now);
if (nextPhaseEvent != null) {
// STEPH Harden since event could be processed twice
dao.createNextPhaseEvent(subscription.getId(), nextPhaseEvent);
@@ -163,4 +168,8 @@ public class Engine implements IEventListener {
return dao;
}
+ public IPlanAligner getPlanAligner() {
+ return planAligner;
+ }
+
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
index 65a7cdb..ddeaf00 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/engine/dao/EntitlementDao.java
@@ -42,7 +42,7 @@ import com.ning.billing.entitlement.events.IEvent.EventType;
import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.entitlement.events.user.IUserEvent;
import com.ning.billing.entitlement.exceptions.EntitlementError;
-import com.ning.billing.entitlement.glue.IEngineConfig;
+import com.ning.billing.entitlement.glue.IEntitlementConfig;
import com.ning.billing.util.Hostname;
import com.ning.billing.util.clock.IClock;
@@ -54,11 +54,11 @@ public class EntitlementDao implements IEntitlementDao {
private final ISubscriptionSqlDao subscriptionsDao;
private final IBundleSqlDao bundlesDao;
private final IEventSqlDao eventsDao;
- private final IEngineConfig config;
+ private final IEntitlementConfig config;
private final String hostname;
@Inject
- public EntitlementDao(DBI dbi, IClock clock, IEngineConfig config) {
+ public EntitlementDao(DBI dbi, IClock clock, IEntitlementConfig config) {
this.clock = clock;
this.config = config;
this.subscriptionsDao = dbi.onDemand(ISubscriptionSqlDao.class);
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEvent.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEvent.java
index f57ac4a..9c6bbba 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEvent.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/phase/PhaseEvent.java
@@ -22,6 +22,8 @@ import org.joda.time.DateTime;
import com.ning.billing.catalog.api.IPlan;
import com.ning.billing.catalog.api.IPlanPhase;
+import com.ning.billing.entitlement.alignment.IPlanAligner.TimedPhase;
+import com.ning.billing.entitlement.api.user.Subscription;
import com.ning.billing.entitlement.events.EventBase;
import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
@@ -71,4 +73,12 @@ public class PhaseEvent extends EventBase implements IPhaseEvent {
+ ", isActive()=" + isActive() + "]\n";
}
+ public static final IPhaseEvent getNextPhaseEvent(TimedPhase nextTimedPhase, Subscription subscription, DateTime now) {
+ return (nextTimedPhase == null) ?
+ null :
+ new PhaseEvent(subscription.getId(), nextTimedPhase.getPhase(), now, nextTimedPhase.getStartPhase(),
+ now, subscription.getActiveVersion());
+
+ }
+
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java
index 6a06aa8..4e2944e 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventBase.java
@@ -21,7 +21,9 @@ import java.util.UUID;
import org.joda.time.DateTime;
import com.ning.billing.catalog.api.IPlan;
-import com.ning.billing.entitlement.alignment.EntitlementAlignment;
+import com.ning.billing.entitlement.alignment.IPlanAligner;
+import com.ning.billing.entitlement.alignment.PlanAligner;
+import com.ning.billing.entitlement.engine.core.Engine;
import com.ning.billing.entitlement.events.EventBase;
import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
@@ -34,15 +36,25 @@ public class ApiEventBase extends EventBase implements IUserEvent {
private final String eventPriceList;
- public ApiEventBase(UUID subscriptionId, DateTime bundleStartDate, DateTime processed, IPlan eventPlan,
+ public ApiEventBase(UUID subscriptionId, DateTime bundleStartDate, DateTime processed, String planName, String phaseName,
String priceList, DateTime requestedDate, ApiEventType eventType, DateTime effectiveDate, long activeVersion) {
super(subscriptionId, requestedDate, effectiveDate, processed, activeVersion, true);
this.eventType = eventType;
this.eventPriceList = priceList;
- this.eventPlan = (eventPlan != null) ? eventPlan.getName() : null;
- this.eventPlanPhase = (eventPlan != null) ? getPhaseName(eventPlan, bundleStartDate, effectiveDate) : null;
+ this.eventPlan = planName;
+ this.eventPlanPhase = phaseName;
}
+ public ApiEventBase(UUID subscriptionId, DateTime bundleStartDate, DateTime processed,
+ DateTime requestedDate, ApiEventType eventType, DateTime effectiveDate, long activeVersion) {
+ super(subscriptionId, requestedDate, effectiveDate, processed, activeVersion, true);
+ this.eventType = eventType;
+ this.eventPriceList = null;
+ this.eventPlan = null;
+ this.eventPlanPhase = null;
+ }
+
+
public ApiEventBase(UUID id, UUID subscriptionId, DateTime processed, String eventPlan, String eventPhase,
String priceList, DateTime requestedDate, ApiEventType eventType, DateTime effectiveDate, long activeVersion,
boolean isActive, UUID processingOwner, DateTime nextAvailableProcessingTime,IEventLyfecycleState processingState) {
@@ -97,15 +109,4 @@ public class ApiEventBase extends EventBase implements IUserEvent {
+ ", getSubscriptionId()=" + getSubscriptionId()
+ ", isActive()=" + isActive() + "]";
}
-
- private String getPhaseName(IPlan eventPlan, DateTime bundleStartDate, DateTime effectiveDate) {
-
- if (eventType != ApiEventType.CREATE && eventType != ApiEventType.CHANGE) {
- return null;
- }
- EntitlementAlignment align = new EntitlementAlignment(bundleStartDate, eventPlan, effectiveDate);
- return align.getCurrentTimedPhase().getPhase().getName();
- }
-
-
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCancel.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCancel.java
index 1ea1b57..a3806d2 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCancel.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCancel.java
@@ -26,7 +26,7 @@ import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
public class ApiEventCancel extends ApiEventBase {
public ApiEventCancel(UUID subscriptionId, DateTime bundleStartDate, DateTime now, DateTime requestedDate, DateTime effectiveDate, long version) {
- super(subscriptionId, bundleStartDate, now, null, null, requestedDate, ApiEventType.CANCEL, effectiveDate, version);
+ super(subscriptionId, bundleStartDate, now, requestedDate, ApiEventType.CANCEL, effectiveDate, version);
}
public ApiEventCancel(UUID id, UUID subscriptionId, DateTime processed, String eventPlan, String eventPhase,
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventChange.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventChange.java
index bdb0a38..40584f5 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventChange.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventChange.java
@@ -27,8 +27,9 @@ import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
public class ApiEventChange extends ApiEventBase {
- public ApiEventChange(UUID subscriptionId, DateTime bundleStartDate, DateTime now, IPlan eventPlan, String priceList, DateTime requestedDate, DateTime effectiveDate, long version) {
- super(subscriptionId, bundleStartDate, now, eventPlan, priceList, requestedDate, ApiEventType.CHANGE, effectiveDate, version);
+ public ApiEventChange(UUID subscriptionId, DateTime bundleStartDate, DateTime now, String planName, String phaseName, String priceList,
+ DateTime requestedDate, DateTime effectiveDate, long version) {
+ super(subscriptionId, bundleStartDate, now, planName, phaseName, priceList, requestedDate, ApiEventType.CHANGE, effectiveDate, version);
}
public ApiEventChange(UUID id, UUID subscriptionId, DateTime processed, String eventPlan, String eventPhase, String priceList,
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCreate.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCreate.java
index 3b2588b..2b12e7e 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCreate.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventCreate.java
@@ -26,9 +26,9 @@ import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
public class ApiEventCreate extends ApiEventBase {
- public ApiEventCreate(UUID subscriptionId, DateTime bundleStartDate, DateTime now, IPlan eventPlan, String priceList,
+ public ApiEventCreate(UUID subscriptionId, DateTime bundleStartDate, DateTime now, String planName, String phaseName, String priceList,
DateTime requestedDate, DateTime effectiveDate, long version) {
- super(subscriptionId, bundleStartDate, now, eventPlan, priceList, requestedDate, ApiEventType.CREATE, effectiveDate, version);
+ super(subscriptionId, bundleStartDate, now, planName, phaseName, priceList, requestedDate, ApiEventType.CREATE, effectiveDate, version);
}
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventPause.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventPause.java
index cd70804..a6ff4b4 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventPause.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventPause.java
@@ -27,7 +27,7 @@ import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
public class ApiEventPause extends ApiEventBase {
public ApiEventPause(UUID subscriptionId, DateTime now, DateTime requestedDate, DateTime effectiveDate, long version) {
- super(subscriptionId, null, now, null, null, requestedDate, ApiEventType.PAUSE, effectiveDate, version);
+ super(subscriptionId, null, now, requestedDate, ApiEventType.PAUSE, effectiveDate, version);
}
public ApiEventPause(UUID id, UUID subscriptionId, DateTime processed, String eventPlan, String eventPhase,
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventResume.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventResume.java
index 05a2461..f8bf26f 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventResume.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventResume.java
@@ -28,7 +28,7 @@ import com.ning.billing.entitlement.events.IEventLyfecycle.IEventLyfecycleState;
public class ApiEventResume extends ApiEventBase {
public ApiEventResume(UUID subscriptionId, DateTime now, DateTime requestedDate, DateTime effectiveDate, long version) {
- super(subscriptionId, null, now, null, null, requestedDate, ApiEventType.RESUME, effectiveDate, version);
+ super(subscriptionId, null, now, requestedDate, ApiEventType.RESUME, effectiveDate, version);
}
public ApiEventResume(UUID id, UUID subscriptionId, DateTime processed, String eventPlan, String eventPhase,
diff --git a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventUncancel.java b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventUncancel.java
index a5c75a8..b5433f1 100644
--- a/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventUncancel.java
+++ b/entitlement/src/main/java/com/ning/billing/entitlement/events/user/ApiEventUncancel.java
@@ -24,7 +24,7 @@ import org.joda.time.DateTime;
public class ApiEventUncancel extends ApiEventBase {
public ApiEventUncancel(UUID subscriptionId, DateTime bundleStartDate, DateTime now, DateTime requestedDate, DateTime effectiveDate, long version) {
- super(subscriptionId, bundleStartDate, now, null, null, requestedDate, ApiEventType.UNCANCEL, effectiveDate, version);
+ super(subscriptionId, bundleStartDate, now, requestedDate, ApiEventType.UNCANCEL, effectiveDate, version);
}
public ApiEventUncancel(UUID id, UUID subscriptionId, DateTime processed, String eventPlan, String eventPhase,
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
index 6433911..9591ee6 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/ApiTestListener.java
@@ -62,7 +62,7 @@ public class ApiTestListener implements IApiListener {
}
}
if (!completed) {
- log.warn("ApiTestListener did not complete in " + timeout + " ms");
+ log.debug("ApiTestListener did not complete in " + timeout + " ms");
}
return completed;
}
@@ -72,15 +72,15 @@ public class ApiTestListener implements IApiListener {
}
private void notifyIfStackEmpty() {
- log.info("notifyIfStackEmpty ENTER");
+ log.debug("notifyIfStackEmpty ENTER");
synchronized (this) {
if (nextExpectedEvent.isEmpty()) {
- log.info("notifyIfStackEmpty EMPTY");
+ log.debug("notifyIfStackEmpty EMPTY");
completed = true;
notify();
}
}
- log.info("notifyIfStackEmpty EXIT");
+ log.debug("notifyIfStackEmpty EXIT");
}
private void assertEqualsNicely(NextEvent expected, NextEvent real) {
@@ -100,35 +100,35 @@ public class ApiTestListener implements IApiListener {
@Override
public void subscriptionCreated(ISubscriptionTransition created) {
- log.info("-> Got event CREATED");
+ log.debug("-> Got event CREATED");
assertEqualsNicely(nextExpectedEvent.pop(), NextEvent.CREATE);
notifyIfStackEmpty();
}
@Override
public void subscriptionCancelled(ISubscriptionTransition cancelled) {
- log.info("-> Got event CANCEL");
+ log.debug("-> Got event CANCEL");
assertEqualsNicely(nextExpectedEvent.pop(), NextEvent.CANCEL);
notifyIfStackEmpty();
}
@Override
public void subscriptionChanged(ISubscriptionTransition changed) {
- log.info("-> Got event CHANGE");
+ log.debug("-> Got event CHANGE");
assertEqualsNicely(nextExpectedEvent.pop(), NextEvent.CHANGE);
notifyIfStackEmpty();
}
@Override
public void subscriptionPaused(ISubscriptionTransition paused) {
- log.info("-> Got event PAUSE");
+ log.debug("-> Got event PAUSE");
assertEqualsNicely(nextExpectedEvent.pop(), NextEvent.PAUSE);
notifyIfStackEmpty();
}
@Override
public void subscriptionResumed(ISubscriptionTransition resumed) {
- log.info("-> Got event RESUME");
+ log.debug("-> Got event RESUME");
assertEqualsNicely(nextExpectedEvent.pop(), NextEvent.RESUME);
notifyIfStackEmpty();
}
@@ -136,7 +136,7 @@ public class ApiTestListener implements IApiListener {
@Override
public void subscriptionPhaseChanged(
ISubscriptionTransition phaseChanged) {
- log.info("-> Got event PHASE");
+ log.debug("-> Got event PHASE");
assertEqualsNicely(nextExpectedEvent.pop(), NextEvent.PHASE);
notifyIfStackEmpty();
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
index 95a5b51..bc4adc5 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiBase.java
@@ -55,7 +55,7 @@ import com.ning.billing.entitlement.events.IEvent;
import com.ning.billing.entitlement.events.phase.IPhaseEvent;
import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.entitlement.events.user.IUserEvent;
-import com.ning.billing.entitlement.glue.IEngineConfig;
+import com.ning.billing.entitlement.glue.IEntitlementConfig;
import com.ning.billing.util.clock.ClockMock;
import com.ning.billing.util.clock.IClock;
@@ -69,7 +69,7 @@ public abstract class TestUserApiBase {
protected IUserApi entitlementApi;
protected IBillingApi billingApi;
protected ICatalogUserApi catalogApi;
- protected IEngineConfig config;
+ protected IEntitlementConfig config;
protected IEntitlementDao dao;
protected ClockMock clock;
@@ -109,7 +109,7 @@ public abstract class TestUserApiBase {
entitlementApi = g.getInstance(IUserApi.class);
catalogApi = g.getInstance(ICatalogUserApi.class);
billingApi = g.getInstance(IBillingApi.class);
- config = g.getInstance(IEngineConfig.class);
+ config = g.getInstance(IEntitlementConfig.class);
dao = g.getInstance(IEntitlementDao.class);
clock = (ClockMock) g.getInstance(IClock.class);
try {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
index 6a07d25..8816503 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlan.java
@@ -37,7 +37,7 @@ import com.ning.billing.catalog.api.IDuration;
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.catalog.api.PlanAlignment;
+import com.ning.billing.catalog.api.PlanAlignmentChange;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
import com.ning.billing.entitlement.events.IEvent;
@@ -211,11 +211,11 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
}
- protected void testChangePlanSubscriptionAlignEOTWithChargeThroughDateReal() {
- tChangePlanSubscriptionAlignEOTWithChargeThroughDate("Shotgun", BillingPeriod.ANNUAL, "standard", "Assault-Rifle", BillingPeriod.ANNUAL, "rescue");
+ protected void testChangePlanChangePlanAlignEOTWithChargeThroughDateReal() {
+ tChangePlanChangePlanAlignEOTWithChargeThroughDate("Shotgun", BillingPeriod.ANNUAL, "standard", "Assault-Rifle", BillingPeriod.ANNUAL, "rescue");
}
- private void tChangePlanSubscriptionAlignEOTWithChargeThroughDate(String fromProd, BillingPeriod fromTerm, String fromPlanSet,
+ private void tChangePlanChangePlanAlignEOTWithChargeThroughDate(String fromProd, BillingPeriod fromTerm, String fromPlanSet,
String toProd, BillingPeriod toTerm, String toPlanSet) {
log.info("Starting testChangePlanBundleAlignEOTWithChargeThroughDate");
@@ -328,7 +328,6 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
assertNotNull(currentPlan);
assertEquals(currentPlan.getProduct().getName(), "Assault-Rifle");
assertEquals(currentPlan.getProduct().getCategory(), ProductCategory.BASE);
- assertEquals(currentPlan.getPlanAlignment(), PlanAlignment.START_OF_BUNDLE);
assertEquals(currentPlan.getBillingPeriod(), BillingPeriod.ANNUAL);
IPlanPhase currentPhase = subscription.getCurrentPhase();
@@ -379,7 +378,6 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
assertNotNull(currentPlan);
assertEquals(currentPlan.getProduct().getName(), "Assault-Rifle");
assertEquals(currentPlan.getProduct().getCategory(), ProductCategory.BASE);
- assertEquals(currentPlan.getPlanAlignment(), PlanAlignment.START_OF_BUNDLE);
assertEquals(currentPlan.getBillingPeriod(), BillingPeriod.ANNUAL);
IPlanPhase currentPhase = subscription.getCurrentPhase();
@@ -397,7 +395,6 @@ public abstract class TestUserApiChangePlan extends TestUserApiBase {
assertNotNull(currentPlan);
assertEquals(currentPlan.getProduct().getName(), "Pistol");
assertEquals(currentPlan.getProduct().getCategory(), ProductCategory.BASE);
- assertEquals(currentPlan.getPlanAlignment(), PlanAlignment.START_OF_BUNDLE);
assertEquals(currentPlan.getBillingPeriod(), BillingPeriod.ANNUAL);
currentPhase = subscription.getCurrentPhase();
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
index 157b8ee..56c1a74 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanMemory.java
@@ -33,7 +33,6 @@ public class TestUserApiChangePlanMemory extends TestUserApiChangePlan {
@Test(enabled=true, groups={"fast"})
public void testChangePlanBundleAlignEOTWithNoChargeThroughDate() {
- System.err.println("STEPH THE TEST");
invokeRealMethod(this);
}
@@ -48,11 +47,6 @@ public class TestUserApiChangePlanMemory extends TestUserApiChangePlan {
}
@Test(enabled=true, groups={"fast"})
- public void testChangePlanSubscriptionAlignEOTWithChargeThroughDate() {
- invokeRealMethod(this);
- }
-
- @Test(enabled=true, groups={"fast"})
public void testMultipleChangeLastIMM() {
invokeRealMethod(this);
}
@@ -62,16 +56,10 @@ public class TestUserApiChangePlanMemory extends TestUserApiChangePlan {
invokeRealMethod(this);
}
- @Test(enabled=false, groups={"stress"})
- public void stressTest() {
- for (int i = 0; i < 20; i++) {
- cleanupTest();
- setupTest();
- testMultipleChangeLastEOT();
- cleanupTest();
- setupTest();
- testMultipleChangeLastIMM();
- }
+ // STEPH set to false until we implement rescue example.
+ @Test(enabled=false, groups={"fast"})
+ public void testChangePlanChangePlanAlignEOTWithChargeThroughDate() {
+ invokeRealMethod(this);
}
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java
index 689dafa..5a5175a 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiChangePlanSql.java
@@ -69,17 +69,19 @@ public class TestUserApiChangePlanSql extends TestUserApiChangePlan {
}
@Test(enabled=true, groups={"sql"})
- public void testChangePlanSubscriptionAlignEOTWithChargeThroughDate() {
+ public void testMultipleChangeLastIMM() {
invokeRealMethod(this);
}
@Test(enabled=true, groups={"sql"})
- public void testMultipleChangeLastIMM() {
+ public void testMultipleChangeLastEOT() {
invokeRealMethod(this);
}
- @Test(enabled=true, groups={"sql"})
- public void testMultipleChangeLastEOT() {
+ // STEPH rescue not implemented
+ @Test(enabled=false, groups={"sql"})
+ public void testChangePlanChangePlanAlignEOTWithChargeThroughDate() {
invokeRealMethod(this);
}
+
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
index 26fdcb0..44c126c 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiCreate.java
@@ -32,7 +32,7 @@ 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.PhaseType;
-import com.ning.billing.catalog.api.PlanAlignment;
+import com.ning.billing.catalog.api.PlanAlignmentChange;
import com.ning.billing.catalog.api.ProductCategory;
import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
import com.ning.billing.entitlement.events.IEvent;
@@ -70,7 +70,6 @@ public abstract class TestUserApiCreate extends TestUserApiBase {
assertNotNull(currentPlan);
assertEquals(currentPlan.getProduct().getName(), productName);
assertEquals(currentPlan.getProduct().getCategory(), ProductCategory.BASE);
- assertEquals(currentPlan.getPlanAlignment(), PlanAlignment.START_OF_BUNDLE);
assertEquals(currentPlan.getBillingPeriod(), BillingPeriod.MONTHLY);
IPlanPhase currentPhase = subscription.getCurrentPhase();
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
new file mode 100644
index 0000000..3fb58ee
--- /dev/null
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/api/user/TestUserApiDemos.java
@@ -0,0 +1,201 @@
+/*
+ * 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.entitlement.api.user;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.slf4j.Logger;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
+import com.ning.billing.catalog.api.BillingPeriod;
+import com.ning.billing.catalog.api.IDuration;
+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.catalog.api.ProductCategory;
+import com.ning.billing.entitlement.api.ApiTestListener.NextEvent;
+import com.ning.billing.entitlement.glue.EngineModuleSqlMock;
+import com.ning.billing.util.clock.Clock;
+
+public class TestUserApiDemos extends TestUserApiBase {
+
+ @Override
+ protected Injector getInjector() {
+ return Guice.createInjector(Stage.DEVELOPMENT, new EngineModuleSqlMock());
+ }
+
+ /**
+ * Initial demo for BP entitlement:
+ * 1. Create a Subscription
+ * 2. ChangePlan while in trial
+ * -> Change is IMM
+ * -> Trial is still 30 days long
+ * 3. Move through 2nd Phase
+ * 4. ChangePlan EOT
+ * -> Show Change pending
+ * 5. Other ChangePlan EOT
+ * -> Show it supercedes the first one
+ * 6. Move to EOT
+ * 7. Move to next Phase
+ * 8. Cancel EOT
+ */
+ @Test(enabled=true, groups="demos")
+ public void testDemo1() {
+
+ try {
+ System.out.println("DEMO 1 START");
+
+ /* STEP 1. CREATE SUBSCRIPTION */
+ Subscription subscription = createSubscription("Assault-Rifle", BillingPeriod.MONTHLY, "gunclubDiscount");
+ IPlanPhase trialPhase = subscription.getCurrentPhase();
+ assertEquals(trialPhase.getPhaseType(), PhaseType.TRIAL);
+
+ displayState(subscription.getId(), "STEP 1. CREATED SUBSCRIPTION");
+
+ /* STEP 2. CHANGE PLAN WHILE IN TRIAL */
+ testListener.pushExpectedEvent(NextEvent.CHANGE);
+ subscription.changePlan("Assault-Rifle", BillingPeriod.ANNUAL, "gunclubDiscount");
+ assertTrue(testListener.isCompleted(3000));
+
+ displayState(subscription.getId(), "STEP 2. CHANGED PLAN WHILE IN TRIAL");
+
+ /* STEP 3. MOVE TO DISCOUNT PHASE */
+ testListener.pushExpectedEvent(NextEvent.PHASE);
+ clock.setDeltaFromReality(trialPhase.getDuration(), DAY_IN_MS);
+ assertTrue(testListener.isCompleted(3000));
+
+ displayState(subscription.getId(), "STEP 3. MOVE TO DISCOUNT PHASE");
+
+ /* STEP 4. SET CTD AND CHANGE PLAN EOT */
+ List<IDuration> durationList = new ArrayList<IDuration>();
+ durationList.add(trialPhase.getDuration());
+ DateTime startDiscountPhase = Clock.addDuration(subscription.getStartDate(), durationList);
+
+ IDuration ctd = getDurationMonth(1);
+ DateTime newChargedThroughDate = Clock.addDuration(startDiscountPhase, ctd);
+ billingApi.setChargedThroughDate(subscription.getId(), newChargedThroughDate);
+ subscription = (Subscription) entitlementApi.getSubscriptionFromId(subscription.getId());
+
+ testListener.pushExpectedEvent(NextEvent.CHANGE);
+ subscription.changePlan("Shotgun", BillingPeriod.ANNUAL, "gunclubDiscount");
+ assertFalse(testListener.isCompleted(2000));
+ testListener.reset();
+
+ displayState(subscription.getId(), "STEP 4. SET CTD AND CHANGE PLAN EOT (Shotgun)");
+
+ /* STEP 5. CHANGE AGAIN */
+ testListener.pushExpectedEvent(NextEvent.CHANGE);
+ subscription.changePlan("Pistol", BillingPeriod.ANNUAL, "gunclubDiscount");
+ assertFalse(testListener.isCompleted(2000));
+ testListener.reset();
+
+ displayState(subscription.getId(), "STEP 5. CHANGE AGAIN EOT (Pistol)");
+
+ /* STEP 6. MOVE TO EOT AND CHECK CHANGE OCCURED */
+ testListener.pushExpectedEvent(NextEvent.CHANGE);
+ clock.addDeltaFromReality(ctd);
+ assertTrue(testListener.isCompleted(2000));
+
+ IPlan currentPlan = subscription.getCurrentPlan();
+ assertNotNull(currentPlan);
+ assertEquals(currentPlan.getProduct().getName(), "Pistol");
+ assertEquals(currentPlan.getProduct().getCategory(), ProductCategory.BASE);
+ assertEquals(currentPlan.getBillingPeriod(), BillingPeriod.ANNUAL);
+
+ IPlanPhase currentPhase = subscription.getCurrentPhase();
+ assertNotNull(currentPhase);
+ assertEquals(currentPhase.getPhaseType(), PhaseType.DISCOUNT);
+
+ displayState(subscription.getId(), "STEP 6. MOVE TO EOT");
+
+ /* STEP 7. MOVE TO NEXT PHASE */
+ testListener.pushExpectedEvent(NextEvent.PHASE);
+ clock.addDeltaFromReality(currentPhase.getDuration());
+ assertTrue(testListener.isCompleted(3000));
+ subscription = (Subscription) entitlementApi.getSubscriptionFromId(subscription.getId());
+
+ currentPlan = subscription.getCurrentPlan();
+ assertNotNull(currentPlan);
+ assertEquals(currentPlan.getProduct().getName(), "Pistol");
+ assertEquals(currentPlan.getProduct().getCategory(), ProductCategory.BASE);
+ assertEquals(currentPlan.getBillingPeriod(), BillingPeriod.ANNUAL);
+
+ currentPhase = subscription.getCurrentPhase();
+ assertNotNull(currentPhase);
+ assertEquals(currentPhase.getPhaseType(), PhaseType.EVERGREEN);
+
+ displayState(subscription.getId(), "STEP 7. MOVE TO NEXT PHASE");
+
+ /* STEP 8. CANCEL IMM (NO CTD) */
+ testListener.pushExpectedEvent(NextEvent.CANCEL);
+ subscription.cancel();
+
+ displayState(subscription.getId(), "STEP 8. CANCELLATION");
+
+ } catch (EntitlementUserApiException e) {
+ Assert.fail(e.getMessage());
+ }
+
+ }
+
+
+ private void displayState(UUID subscriptionId, String stepMsg) {
+
+ System.out.println("");
+ System.out.println("******\t STEP " + stepMsg + " **************");
+
+ Subscription subscription = (Subscription) entitlementApi.getSubscriptionFromId(subscriptionId);
+
+
+ IPlan currentPlan = subscription.getCurrentPlan();
+ IPlanPhase currentPhase = subscription.getCurrentPhase();
+ String priceList = subscription.getCurrentPriceList();
+ System.out.println("");
+ System.out.println("\t CURRENT TIME = " + clock.getUTCNow());
+ System.out.println("");
+ System.out.println("\t CURRENT STATE = " + subscription.getState());
+ System.out.println("\t CURRENT PRODUCT = " + ((currentPlan == null) ? "NONE" : currentPlan.getProduct().getName()));
+ System.out.println("\t CURRENT TERM = " + ((currentPlan == null) ? "NONE" : currentPlan.getBillingPeriod().toString()));
+ System.out.println("\t CURRENT PHASE = " + ((currentPhase == null) ? "NONE" : currentPhase.getPhaseType()));
+ System.out.println("\t CURRENT PRICE LIST = " + ((priceList == null) ? "NONE" : priceList));
+ System.out.println("\t CURRENT \'SLUG\' = " + ((currentPhase == null) ? "NONE" : currentPhase.getName()));
+
+ System.out.println("");
+
+ }
+
+ @Test(enabled= true, groups={"stress"})
+ public void stressTest() {
+ for (int i = 0; i < 100; i++) {
+ cleanupTest();
+ setupTest();
+ testDemo1();
+ }
+ }
+}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorMemoryMock.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorMemoryMock.java
index 2c35a8e..4089936 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorMemoryMock.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/core/ApiEventProcessorMemoryMock.java
@@ -21,14 +21,14 @@ import java.util.List;
import com.google.inject.Inject;
import com.ning.billing.entitlement.engine.dao.IEntitlementDao;
import com.ning.billing.entitlement.events.IEvent;
-import com.ning.billing.entitlement.glue.IEngineConfig;
+import com.ning.billing.entitlement.glue.IEntitlementConfig;
import com.ning.billing.util.clock.IClock;
public class ApiEventProcessorMemoryMock extends ApiEventProcessorBase {
@Inject
- public ApiEventProcessorMemoryMock(IClock clock, IEntitlementDao dao, IEngineConfig config) {
+ public ApiEventProcessorMemoryMock(IClock clock, IEntitlementDao dao, IEntitlementConfig config) {
super(clock, dao, config);
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoMemoryMock.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoMemoryMock.java
index 45754d0..143b069 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoMemoryMock.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoMemoryMock.java
@@ -42,7 +42,7 @@ import com.ning.billing.entitlement.events.phase.IPhaseEvent;
import com.ning.billing.entitlement.events.phase.PhaseEvent;
import com.ning.billing.entitlement.events.user.ApiEventType;
import com.ning.billing.entitlement.events.user.IUserEvent;
-import com.ning.billing.entitlement.glue.IEngineConfig;
+import com.ning.billing.entitlement.glue.IEntitlementConfig;
import com.ning.billing.util.clock.IClock;
public class EntitlementDaoMemoryMock implements IEntitlementDao, IEntitlementDaoMock {
@@ -53,10 +53,10 @@ public class EntitlementDaoMemoryMock implements IEntitlementDao, IEntitlementDa
private final List<ISubscription> subscriptions;
private final TreeSet<IEvent> events;
private final IClock clock;
- private final IEngineConfig config;
+ private final IEntitlementConfig config;
@Inject
- public EntitlementDaoMemoryMock(IClock clock, IEngineConfig config) {
+ public EntitlementDaoMemoryMock(IClock clock, IEntitlementConfig config) {
super();
this.clock = clock;
this.config = config;
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoSqlMock.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoSqlMock.java
index 0814059..114021e 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoSqlMock.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/EntitlementDaoSqlMock.java
@@ -24,7 +24,7 @@ import org.skife.jdbi.v2.sqlobject.mixins.CloseMe;
import org.skife.jdbi.v2.sqlobject.mixins.Transactional;
import com.google.inject.Inject;
-import com.ning.billing.entitlement.glue.IEngineConfig;
+import com.ning.billing.entitlement.glue.IEntitlementConfig;
import com.ning.billing.util.clock.IClock;
public class EntitlementDaoSqlMock extends EntitlementDao implements IEntitlementDaoMock {
@@ -32,7 +32,7 @@ public class EntitlementDaoSqlMock extends EntitlementDao implements IEntitlemen
private final ResetSqlDao resetDao;
@Inject
- public EntitlementDaoSqlMock(DBI dbi, IClock clock, IEngineConfig config) {
+ public EntitlementDaoSqlMock(DBI dbi, IClock clock, IEntitlementConfig config) {
super(dbi, clock, config);
this.resetDao = dbi.onDemand(ResetSqlDao.class);
}
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/TestEntitlementDao.java b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/TestEntitlementDao.java
index 0694fac..cd6da83 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/TestEntitlementDao.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/engine/dao/TestEntitlementDao.java
@@ -61,7 +61,7 @@ public class TestEntitlementDao extends TestUserApiBase {
DateTime now = new DateTime();
IPlan plan = catalog.getPlan(productName, term, planSetName);
- IEvent event = new ApiEventCreate(UUID.randomUUID(), now, now, plan,planSetName, now, now, 1);
+ IEvent event = new ApiEventCreate(UUID.randomUUID(), now, now, plan.getName(), "evergreen", planSetName, now, now, 1);
dao.insertEvent(event);
sleep();
@@ -105,7 +105,7 @@ public class TestEntitlementDao extends TestUserApiBase {
String planSetName = "standard";
IPlan plan = catalog.getPlan(productName, term, planSetName);
- final IEvent event = new ApiEventCreate(UUID.randomUUID(), now, now, plan, planSetName, now, now, 1);
+ final IEvent event = new ApiEventCreate(UUID.randomUUID(), now, now, plan.getName(), "evergreen", planSetName, now, now, 1);
dao.inTransaction(new Transaction<Void, ISubscriptionSqlDao>() {
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleMemoryMock.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleMemoryMock.java
index 0f422f1..70120e7 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleMemoryMock.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleMemoryMock.java
@@ -21,13 +21,13 @@ import com.ning.billing.entitlement.engine.core.ApiEventProcessorMemoryMock;
import com.ning.billing.entitlement.engine.core.IApiEventProcessor;
import com.ning.billing.entitlement.engine.dao.EntitlementDaoMemoryMock;
import com.ning.billing.entitlement.engine.dao.IEntitlementDao;
-import com.ning.billing.entitlement.glue.EngineModule;
+import com.ning.billing.entitlement.glue.EntitlementModule;
import com.ning.billing.util.clock.Clock;
import com.ning.billing.util.clock.ClockMock;
import com.ning.billing.util.clock.IClock;
-public class EngineModuleMemoryMock extends EngineModule {
+public class EngineModuleMemoryMock extends EntitlementModule {
@Override
protected void installApiEventProcessor() {
bind(IApiEventProcessor.class).to(ApiEventProcessorMemoryMock.class).asEagerSingleton();
diff --git a/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleSqlMock.java b/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleSqlMock.java
index 3e8a0b4..214ab3e 100644
--- a/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleSqlMock.java
+++ b/entitlement/src/test/java/com/ning/billing/entitlement/glue/EngineModuleSqlMock.java
@@ -21,7 +21,7 @@ import com.ning.billing.entitlement.engine.dao.IEntitlementDao;
import com.ning.billing.util.clock.ClockMock;
import com.ning.billing.util.clock.IClock;
-public class EngineModuleSqlMock extends EngineModule {
+public class EngineModuleSqlMock extends EntitlementModule {
@Override
protected void installEntitlementDao() {
diff --git a/entitlement/src/test/resources/log4j.xml b/entitlement/src/test/resources/log4j.xml
index 4f9885b..75abc76 100644
--- a/entitlement/src/test/resources/log4j.xml
+++ b/entitlement/src/test/resources/log4j.xml
@@ -26,7 +26,7 @@
<logger name="com.ning.billing.entitlement">
- <level value="debug"/>
+ <level value="info"/>
</logger>
<root>
entitlement/src/test/resources/testInput.xml 106(+43 -63)
diff --git a/entitlement/src/test/resources/testInput.xml b/entitlement/src/test/resources/testInput.xml
index 7ba09ed..59b9093 100644
--- a/entitlement/src/test/resources/testInput.xml
+++ b/entitlement/src/test/resources/testInput.xml
@@ -40,6 +40,7 @@ Use Cases to do:
xsi:noNamespaceSchemaLocation="../../main/resources/CatalogSchema.xsd ">
<effectiveDate>2011-10-08T00:00:00+00:00</effectiveDate>
+ <catalogName>Firearms</catalogName>
<currencies>
<currency>USD</currency>
@@ -47,14 +48,8 @@ Use Cases to do:
<currency>GBP</currency>
</currencies>
- <productTypes>
- <productType name="Firearms" />
- <productType name="Blade" />
- </productTypes>
-
<products>
<product name="Pistol">
- <type>Firearms</type>
<category>BASE</category>
<available>
<addonProduct>Telescopic-Scope</addonProduct>
@@ -62,11 +57,9 @@ Use Cases to do:
</available>
</product>
<product name="Shotgun">
- <type>Firearms</type>
<category>BASE</category>
</product>
<product name="Assault-Rifle">
- <type>Firearms</type>
<category>BASE</category>
<included>
<addonProduct>Telescopic-Scope</addonProduct>
@@ -76,31 +69,24 @@ Use Cases to do:
</available>
</product>
<product name="Telescopic-Scope">
- <type>Firearms</type>
<category>ADD_ON</category>
</product>
<product name="Laser-Scope">
- <type>Firearms</type>
<category>ADD_ON</category>
</product>
<product name="Holster">
- <type>Firearms</type>
<category>ADD_ON</category>
</product>
<product name="Extra-Ammo">
- <type>Firearms</type>
<category>ADD_ON</category>
</product>
<product name="Refurbish-Maintenance">
- <type>Firearms</type>
<category>ADD_ON</category>
</product>
<product name="Bowie-Knife">
- <type>Blade</type>
<category>BASE</category>
</product>
<product name="Samuri-Sword">
- <type>Blade</type>
<category>BASE</category>
</product>
</products>
@@ -113,39 +99,65 @@ Use Cases to do:
<product>Assault-Rifle</product>
</tier>
</tiers>
- <changeRule>
+ <changePolicyRule>
<qualifier>DEFAULT</qualifier>
<policy>END_OF_TERM</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>TERM_FROM_SHORT_TO_LONG</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeRule>
+ </changePolicyRule>
+ <changePolicyRule>
<qualifier>PRODUCT_FROM_LOW_TO_HIGH</qualifier>
<policy>IMMEDIATE</policy>
- </changeRule>
- <changeCase>
+ </changePolicyRule>
+ <changePolicyCase>
<fromBillingPeriod>MONTHLY</fromBillingPeriod>
<toProduct>Assault-Rifle</toProduct>
<toBillingPeriod>MONTHLY</toBillingPeriod>
<policy>END_OF_TERM</policy>
- </changeCase>
- <changeCase>
+ </changePolicyCase>
+ <changePolicyCase>
<toPriceList>rescue</toPriceList>
<policy>END_OF_TERM</policy>
- </changeCase>
- <changeCase>
+ </changePolicyCase>
+ <changePolicyCase>
<phaseType>TRIAL</phaseType>
<policy>IMMEDIATE</policy>
- </changeCase>
- <cancelCase>
+ </changePolicyCase>
+ <changeAlignmentCase>
+ <alignment>START_OF_SUBSCRIPTION</alignment>
+ </changeAlignmentCase>
+ <changeAlignmentCase>
+ <toPriceList>rescue</toPriceList>
+ <alignment>CHANGE_OF_PLAN</alignment>
+ </changeAlignmentCase>
+ <changeAlignmentCase>
+ <fromPriceList>rescue</fromPriceList>
+ <toPriceList>rescue</toPriceList>
+ <alignment>CHANGE_OF_PRICELIST</alignment>
+ </changeAlignmentCase>
+ <cancelPolicyCase>
<policy>END_OF_TERM</policy>
- </cancelCase>
- <cancelCase>
+ </cancelPolicyCase>
+ <cancelPolicyCase>
<phaseType>TRIAL</phaseType>
<policy>IMMEDIATE</policy>
- </cancelCase>
+ </cancelPolicyCase>
+ <createAlignmentCase>
+ <alignment>START_OF_BUNDLE</alignment>
+ </createAlignmentCase>
+ <billingAlignmentCase>
+ <alignment>ACCOUNT</alignment>
+ </billingAlignmentCase>
+ <billingAlignmentCase>
+ <billingPeriod>ANNUAL</billingPeriod>
+ <alignment>SUBSCRIPTION</alignment>
+ </billingAlignmentCase>
+ <billingAlignmentCase>
+ <productCategory>ADD_ON</productCategory>
+ <alignment>BUNDLE</alignment>
+ </billingAlignmentCase>
</rules>
<plans>
@@ -172,8 +184,6 @@ Use Cases to do:
<price><currency>USD</currency><value>29.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_BUNDLE</planAlignment>
- <billingAlignment>ACCOUNT</billingAlignment>
</plan>
<plan name="shotgun-monthly">
<product>Shotgun</product>
@@ -199,8 +209,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>169.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_BUNDLE</planAlignment>
- <billingAlignment>ACCOUNT</billingAlignment>
</plan>
<plan name="assault-rifle-monthly">
<product>Assault-Rifle</product>
@@ -225,8 +233,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>399.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_BUNDLE</planAlignment>
- <billingAlignment>ACCOUNT</billingAlignment>
</plan>
<plan name="pistol-annual">
<product>Pistol</product>
@@ -251,8 +257,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>199.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_BUNDLE</planAlignment>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
<plan name="shotgun-annual">
<product>Shotgun</product>
@@ -277,8 +281,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>1699.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_BUNDLE</planAlignment>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
<plan name="assault-rifle-annual">
<product>Assault-Rifle</product>
@@ -303,8 +305,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>3999.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_BUNDLE</planAlignment>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
<plan name="pistol-annual-gunclub-discount">
<product>Pistol</product>
@@ -341,8 +341,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>199.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_BUNDLE</planAlignment>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
<plan name="shotgun-annual-gunclub-discount">
<product>Shotgun</product>
@@ -379,8 +377,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>1699.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_BUNDLE</planAlignment>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
<plan name="assault-rifle-annual-gunclub-discount">
<product>Assault-Rifle</product>
@@ -417,8 +413,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>3999.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_BUNDLE</planAlignment>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
<plan name="laser-scope-monthly">
<product>Laser-Scope</product>
@@ -433,8 +427,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>1999.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_BUNDLE</planAlignment>
- <billingAlignment>BUNDLE</billingAlignment>
</plan>
<plan name="telescopic-scope-monthly">
<product>Telescopic-Scope</product>
@@ -449,8 +441,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>999.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_BUNDLE</planAlignment>
- <billingAlignment>BUNDLE</billingAlignment>
</plan>
<plan name="extra-ammo-monthly">
<product>Extra-Ammo</product>
@@ -465,8 +455,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>999.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_BUNDLE</planAlignment>
- <billingAlignment>BUNDLE</billingAlignment>
<plansAllowedInBundle>-1</plansAllowedInBundle> <!-- arbitrary number of these (multipack) -->
</plan>
<plan name="holster-monthly-regular">
@@ -492,8 +480,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>199.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_BUNDLE</planAlignment>
- <billingAlignment>BUNDLE</billingAlignment>
</plan>
<plan name="holster-monthly-special">
<product>Holster</product>
@@ -518,8 +504,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>199.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_SUBSCRIPTION</planAlignment>
- <billingAlignment>BUNDLE</billingAlignment>
</plan>
<plan name="assault-rifle-annual-rescue">
<product>Assault-Rifle</product>
@@ -548,8 +532,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>3999.95</value></price>
</recurringPrice>
</finalPhase>
- <planAlignment>START_OF_SUBSCRIPTION</planAlignment>
- <billingAlignment>SUBSCRIPTION</billingAlignment>
</plan>
<plan name="refurbish-maintenance">
<product>Refurbish-Maintenance</product>
@@ -570,8 +552,6 @@ Use Cases to do:
<price><currency>GBP</currency><value>599.95</value></price>
</fixedPrice>
</finalPhase>
- <planAlignment>START_OF_SUBSCRIPTION</planAlignment>
- <billingAlignment>BUNDLE</billingAlignment>
</plan>
</plans>
<priceLists>
pom.xml 4(+2 -2)
diff --git a/pom.xml b/pom.xml
index 23f4a7e..a6d4be2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -121,8 +121,8 @@
</dependency>
<dependency>
<groupId>com.ning.jetty</groupId>
- <artifactId>ning-service-skeleton-core</artifactId>
- <version>0.0.2</version>
+ <artifactId>ning-service-skeleton-utils</artifactId>
+ <version>0.0.6-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>