killbill-memoizeit
Changes
subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java 4(+3 -1)
Details
diff --git a/account/src/test/java/org/killbill/billing/account/dao/MockAccountDao.java b/account/src/test/java/org/killbill/billing/account/dao/MockAccountDao.java
index e9715dd..a06aa3f 100644
--- a/account/src/test/java/org/killbill/billing/account/dao/MockAccountDao.java
+++ b/account/src/test/java/org/killbill/billing/account/dao/MockAccountDao.java
@@ -107,7 +107,9 @@ public class MockAccountDao extends MockEntityDaoBase<AccountModelDao, Account,
@Override
public Pagination<AccountModelDao> searchAccounts(final String searchKey, final Long offset, final Long limit, final InternalTenantContext context) {
final List<AccountModelDao> results = new LinkedList<AccountModelDao>();
+ int maxNbRecords = 0;
for (final AccountModelDao account : getAll(context)) {
+ maxNbRecords++;
if ((account.getName() != null && account.getName().contains(searchKey)) ||
(account.getEmail() != null && account.getEmail().contains(searchKey)) ||
(account.getExternalKey() != null && account.getExternalKey().contains(searchKey)) ||
@@ -116,7 +118,7 @@ public class MockAccountDao extends MockEntityDaoBase<AccountModelDao, Account,
}
}
- return DefaultPagination.<AccountModelDao>build(offset, limit, results);
+ return DefaultPagination.<AccountModelDao>build(offset, limit, maxNbRecords, results);
}
@Override
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java b/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
index d6a2133..6c1c27e 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/dao/MockInvoiceDao.java
@@ -182,7 +182,9 @@ public class MockInvoiceDao extends MockEntityDaoBase<InvoiceModelDao, Invoice,
@Override
public Pagination<InvoiceModelDao> searchInvoices(final String searchKey, final Long offset, final Long limit, final InternalTenantContext context) {
final List<InvoiceModelDao> results = new LinkedList<InvoiceModelDao>();
+ int maxNbRecords = 0;
for (final InvoiceModelDao invoice : getAll(context)) {
+ maxNbRecords++;
if (invoice.getId().toString().equals(searchKey) ||
invoice.getAccountId().toString().equals(searchKey) ||
invoice.getInvoiceNumber().toString().equals(searchKey) ||
@@ -191,7 +193,7 @@ public class MockInvoiceDao extends MockEntityDaoBase<InvoiceModelDao, Invoice,
}
}
- return DefaultPagination.<InvoiceModelDao>build(offset, limit, results);
+ return DefaultPagination.<InvoiceModelDao>build(offset, limit, maxNbRecords, results);
}
@Override
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java
index f09a73f..0429c46 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/PaymentMethodProcessor.java
@@ -56,6 +56,7 @@ import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
import org.killbill.billing.util.callcontext.TenantContext;
import org.killbill.billing.util.config.PaymentConfig;
+import org.killbill.billing.util.entity.DefaultPagination;
import org.killbill.billing.util.entity.Pagination;
import org.killbill.billing.util.entity.dao.DefaultPaginationHelper.EntityPaginationBuilder;
import org.killbill.billing.util.entity.dao.DefaultPaginationHelper.SourcePaginationBuilder;
@@ -70,6 +71,7 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
import com.google.inject.Inject;
import static org.killbill.billing.payment.dispatcher.PaymentPluginDispatcher.dispatchWithExceptionHandling;
@@ -236,7 +238,8 @@ public class PaymentMethodProcessor extends ProcessorBase {
}
public Pagination<PaymentMethod> getPaymentMethods(final Long offset, final Long limit, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) {
- return getEntityPaginationFromPlugins(getAvailablePlugins(),
+ return getEntityPaginationFromPlugins(true,
+ getAvailablePlugins(),
offset,
limit,
new EntityPaginationBuilder<PaymentMethod, PaymentApiException>() {
@@ -279,69 +282,75 @@ public class PaymentMethodProcessor extends ProcessorBase {
}
public Pagination<PaymentMethod> searchPaymentMethods(final String searchKey, final Long offset, final Long limit, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) {
- return getEntityPaginationFromPlugins(getAvailablePlugins(),
- offset,
- limit,
- new EntityPaginationBuilder<PaymentMethod, PaymentApiException>() {
- @Override
- public Pagination<PaymentMethod> build(final Long offset, final Long limit, final String pluginName) throws PaymentApiException {
- return searchPaymentMethods(searchKey, offset, limit, pluginName, withPluginInfo, properties, tenantContext, internalTenantContext);
- }
- }
- );
- }
-
- public Pagination<PaymentMethod> searchPaymentMethods(final String searchKey, final Long offset, final Long limit, final String pluginName,
- final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
if (withPluginInfo) {
- final PaymentPluginApi pluginApi = getPaymentPluginApi(pluginName);
-
- return getEntityPagination(limit,
- new SourcePaginationBuilder<PaymentMethodPlugin, PaymentApiException>() {
- @Override
- public Pagination<PaymentMethodPlugin> build() throws PaymentApiException {
- try {
- return pluginApi.searchPaymentMethods(searchKey, offset, limit, properties, tenantContext);
- } catch (final PaymentPluginApiException e) {
- throw new PaymentApiException(e, ErrorCode.PAYMENT_PLUGIN_SEARCH_PAYMENT_METHODS, pluginName, searchKey);
+ return getEntityPaginationFromPlugins(false,
+ getAvailablePlugins(),
+ offset,
+ limit,
+ new EntityPaginationBuilder<PaymentMethod, PaymentApiException>() {
+ @Override
+ public Pagination<PaymentMethod> build(final Long offset, final Long limit, final String pluginName) throws PaymentApiException {
+ return searchPaymentMethods(searchKey, offset, limit, pluginName, withPluginInfo, properties, tenantContext, internalTenantContext);
+ }
+ }
+ );
+ } else {
+ try {
+ return getEntityPagination(limit,
+ new SourcePaginationBuilder<PaymentMethodModelDao, PaymentApiException>() {
+ @Override
+ public Pagination<PaymentMethodModelDao> build() {
+ return paymentDao.searchPaymentMethods(searchKey, offset, limit, internalTenantContext);
}
- }
- },
- new Function<PaymentMethodPlugin, PaymentMethod>() {
- @Override
- public PaymentMethod apply(final PaymentMethodPlugin paymentMethodPlugin) {
- if (paymentMethodPlugin.getKbPaymentMethodId() == null) {
- // Garbage from the plugin?
- log.debug("Plugin {} returned a payment method without a kbPaymentMethodId for searchKey {}", pluginName, searchKey);
- return null;
+ },
+ new Function<PaymentMethodModelDao, PaymentMethod>() {
+ @Override
+ public PaymentMethod apply(final PaymentMethodModelDao paymentMethodModelDao) {
+ return new DefaultPaymentMethod(paymentMethodModelDao, null);
}
+ }
+ );
+ } catch (final PaymentApiException e) {
+ log.warn("Unable to search through payment methods", e);
+ return new DefaultPagination<PaymentMethod>(offset, limit, null, null, Iterators.<PaymentMethod>emptyIterator());
+ }
+ }
+ }
- final PaymentMethodModelDao paymentMethodModelDao = paymentDao.getPaymentMethodIncludedDeleted(paymentMethodPlugin.getKbPaymentMethodId(), internalTenantContext);
- if (paymentMethodModelDao == null) {
- log.warn("Unable to find payment method id " + paymentMethodPlugin.getKbPaymentMethodId() + " present in plugin " + pluginName);
- return null;
- }
+ public Pagination<PaymentMethod> searchPaymentMethods(final String searchKey, final Long offset, final Long limit, final String pluginName, final boolean withPluginInfo,
+ final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
+ final PaymentPluginApi pluginApi = getPaymentPluginApi(pluginName);
- return new DefaultPaymentMethod(paymentMethodModelDao, paymentMethodPlugin);
+ return getEntityPagination(limit,
+ new SourcePaginationBuilder<PaymentMethodPlugin, PaymentApiException>() {
+ @Override
+ public Pagination<PaymentMethodPlugin> build() throws PaymentApiException {
+ try {
+ return pluginApi.searchPaymentMethods(searchKey, offset, limit, properties, tenantContext);
+ } catch (final PaymentPluginApiException e) {
+ throw new PaymentApiException(e, ErrorCode.PAYMENT_PLUGIN_SEARCH_PAYMENT_METHODS, pluginName, searchKey);
}
}
- );
- } else {
- return getEntityPagination(limit,
- new SourcePaginationBuilder<PaymentMethodModelDao, PaymentApiException>() {
- @Override
- public Pagination<PaymentMethodModelDao> build() {
- return paymentDao.searchPaymentMethods(searchKey, offset, limit, internalTenantContext);
+ },
+ new Function<PaymentMethodPlugin, PaymentMethod>() {
+ @Override
+ public PaymentMethod apply(final PaymentMethodPlugin paymentMethodPlugin) {
+ if (paymentMethodPlugin.getKbPaymentMethodId() == null) {
+ // Garbage from the plugin?
+ log.debug("Plugin {} returned a payment method without a kbPaymentMethodId for searchKey {}", pluginName, searchKey);
+ return null;
}
- },
- new Function<PaymentMethodModelDao, PaymentMethod>() {
- @Override
- public PaymentMethod apply(final PaymentMethodModelDao paymentMethodModelDao) {
- return new DefaultPaymentMethod(paymentMethodModelDao, null);
+
+ final PaymentMethodModelDao paymentMethodModelDao = paymentDao.getPaymentMethodIncludedDeleted(paymentMethodPlugin.getKbPaymentMethodId(), internalTenantContext);
+ if (paymentMethodModelDao == null) {
+ log.warn("Unable to find payment method id " + paymentMethodPlugin.getKbPaymentMethodId() + " present in plugin " + pluginName);
+ return null;
}
+
+ return new DefaultPaymentMethod(paymentMethodModelDao, withPluginInfo ? paymentMethodPlugin : null);
}
- );
- }
+ }
+ );
}
public PaymentMethod getExternalPaymentMethod(final UUID accountId, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext context) throws PaymentApiException {
diff --git a/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java b/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
index 7b39cf1..7aa74e5 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/PaymentProcessor.java
@@ -60,6 +60,7 @@ import org.killbill.billing.tag.TagInternalApi;
import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.InternalCallContextFactory;
import org.killbill.billing.util.callcontext.TenantContext;
+import org.killbill.billing.util.entity.DefaultPagination;
import org.killbill.billing.util.entity.Pagination;
import org.killbill.billing.util.entity.dao.DefaultPaginationHelper.EntityPaginationBuilder;
import org.killbill.billing.util.entity.dao.DefaultPaginationHelper.SourcePaginationBuilder;
@@ -72,6 +73,7 @@ import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
+import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
@@ -206,7 +208,8 @@ public class PaymentProcessor extends ProcessorBase {
public Pagination<Payment> getPayments(final Long offset, final Long limit, final boolean withPluginInfo, final Iterable<PluginProperty> properties,
final TenantContext tenantContext, final InternalTenantContext internalTenantContext) {
- return getEntityPaginationFromPlugins(getAvailablePlugins(),
+ return getEntityPaginationFromPlugins(true,
+ getAvailablePlugins(),
offset,
limit,
new EntityPaginationBuilder<Payment, PaymentApiException>() {
@@ -240,74 +243,80 @@ public class PaymentProcessor extends ProcessorBase {
}
public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) {
- return getEntityPaginationFromPlugins(getAvailablePlugins(),
- offset,
- limit,
- new EntityPaginationBuilder<Payment, PaymentApiException>() {
- @Override
- public Pagination<Payment> build(final Long offset, final Long limit, final String pluginName) throws PaymentApiException {
- return searchPayments(searchKey, offset, limit, pluginName, withPluginInfo, properties, tenantContext, internalTenantContext);
- }
- }
- );
- }
-
- public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final String pluginName, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
if (withPluginInfo) {
- final PaymentPluginApi pluginApi = getPaymentPluginApi(pluginName);
-
- return getEntityPagination(limit,
- new SourcePaginationBuilder<PaymentTransactionInfoPlugin, PaymentApiException>() {
- @Override
- public Pagination<PaymentTransactionInfoPlugin> build() throws PaymentApiException {
- try {
- return pluginApi.searchPayments(searchKey, offset, limit, properties, tenantContext);
- } catch (final PaymentPluginApiException e) {
- throw new PaymentApiException(e, ErrorCode.PAYMENT_PLUGIN_SEARCH_PAYMENTS, pluginName, searchKey);
+ return getEntityPaginationFromPlugins(false,
+ getAvailablePlugins(),
+ offset,
+ limit,
+ new EntityPaginationBuilder<Payment, PaymentApiException>() {
+ @Override
+ public Pagination<Payment> build(final Long offset, final Long limit, final String pluginName) throws PaymentApiException {
+ return searchPayments(searchKey, offset, limit, pluginName, withPluginInfo, properties, tenantContext, internalTenantContext);
+ }
+ }
+ );
+ } else {
+ try {
+ return getEntityPagination(limit,
+ new SourcePaginationBuilder<PaymentModelDao, PaymentApiException>() {
+ @Override
+ public Pagination<PaymentModelDao> build() {
+ return paymentDao.searchPayments(searchKey, offset, limit, internalTenantContext);
+ }
+ },
+ new Function<PaymentModelDao, Payment>() {
+ @Override
+ public Payment apply(final PaymentModelDao paymentModelDao) {
+ return toPayment(paymentModelDao.getId(), null, internalTenantContext);
}
}
+ );
+ } catch (final PaymentApiException e) {
+ log.warn("Unable to search through payments", e);
+ return new DefaultPagination<Payment>(offset, limit, null, null, Iterators.<Payment>emptyIterator());
+ }
+ }
+ }
- },
- new Function<PaymentTransactionInfoPlugin, Payment>() {
- final List<PaymentTransactionInfoPlugin> cachedPaymentTransactions = new LinkedList<PaymentTransactionInfoPlugin>();
-
- @Override
- public Payment apply(final PaymentTransactionInfoPlugin pluginTransaction) {
- if (pluginTransaction.getKbPaymentId() == null) {
- // Garbage from the plugin?
- log.debug("Plugin {} returned a payment without a kbPaymentId for searchKey {}", pluginName, searchKey);
- return null;
- }
+ public Pagination<Payment> searchPayments(final String searchKey, final Long offset, final Long limit, final String pluginName, final boolean withPluginInfo, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
+ final PaymentPluginApi pluginApi = getPaymentPluginApi(pluginName);
- if (cachedPaymentTransactions.isEmpty() ||
- (cachedPaymentTransactions.get(0).getKbPaymentId().equals(pluginTransaction.getKbPaymentId()))) {
- cachedPaymentTransactions.add(pluginTransaction);
- return null;
- } else {
- final Payment result = toPayment(pluginTransaction.getKbPaymentId(), ImmutableList.<PaymentTransactionInfoPlugin>copyOf(cachedPaymentTransactions), internalTenantContext);
- cachedPaymentTransactions.clear();
- cachedPaymentTransactions.add(pluginTransaction);
- return result;
- }
+ return getEntityPagination(limit,
+ new SourcePaginationBuilder<PaymentTransactionInfoPlugin, PaymentApiException>() {
+ @Override
+ public Pagination<PaymentTransactionInfoPlugin> build() throws PaymentApiException {
+ try {
+ return pluginApi.searchPayments(searchKey, offset, limit, properties, tenantContext);
+ } catch (final PaymentPluginApiException e) {
+ throw new PaymentApiException(e, ErrorCode.PAYMENT_PLUGIN_SEARCH_PAYMENTS, pluginName, searchKey);
}
}
- );
- } else {
- return getEntityPagination(limit,
- new SourcePaginationBuilder<PaymentModelDao, PaymentApiException>() {
- @Override
- public Pagination<PaymentModelDao> build() {
- return paymentDao.searchPayments(searchKey, offset, limit, internalTenantContext);
+
+ },
+ new Function<PaymentTransactionInfoPlugin, Payment>() {
+ final List<PaymentTransactionInfoPlugin> cachedPaymentTransactions = new LinkedList<PaymentTransactionInfoPlugin>();
+
+ @Override
+ public Payment apply(final PaymentTransactionInfoPlugin pluginTransaction) {
+ if (pluginTransaction.getKbPaymentId() == null) {
+ // Garbage from the plugin?
+ log.debug("Plugin {} returned a payment without a kbPaymentId for searchKey {}", pluginName, searchKey);
+ return null;
}
- },
- new Function<PaymentModelDao, Payment>() {
- @Override
- public Payment apply(final PaymentModelDao paymentModelDao) {
- return toPayment(paymentModelDao.getId(), null, internalTenantContext);
+
+ if (cachedPaymentTransactions.isEmpty() ||
+ (cachedPaymentTransactions.get(0).getKbPaymentId().equals(pluginTransaction.getKbPaymentId()))) {
+ cachedPaymentTransactions.add(pluginTransaction);
+ return null;
+ } else {
+ final Payment result = toPayment(pluginTransaction.getKbPaymentId(), withPluginInfo ? ImmutableList.<PaymentTransactionInfoPlugin>copyOf(cachedPaymentTransactions) : ImmutableList.<PaymentTransactionInfoPlugin>of(), internalTenantContext);
+ cachedPaymentTransactions.clear();
+ cachedPaymentTransactions.add(pluginTransaction);
+ return result;
}
}
- );
- }
+ }
+ );
}
private Payment performOperation(final boolean isApiPayment, @Nullable final UUID attemptId,
diff --git a/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentMethodSqlDao.sql.stg b/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentMethodSqlDao.sql.stg
index 210d6da..aeccb57 100644
--- a/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentMethodSqlDao.sql.stg
+++ b/payment/src/main/resources/org/killbill/billing/payment/dao/PaymentMethodSqlDao.sql.stg
@@ -54,7 +54,7 @@ getByExternalKey() ::= <<
select <allTableFields()>
from <tableName()>
where external_key = :externalKey
-and is_active = true
+<andCheckSoftDeletionWithComma()>
<AND_CHECK_TENANT()>
;
>>
@@ -80,7 +80,7 @@ select
<allTableFields()>
from <tableName()>
where account_id = :accountId
-and is_active = true
+<andCheckSoftDeletionWithComma()>
<AND_CHECK_TENANT()>
;
>>
@@ -106,7 +106,7 @@ select
<allTableFields("t.")>
from <tableName()> t
where t.plugin_name = :pluginName
-and t.is_active = true
+<andCheckSoftDeletionWithComma("t.")>
<AND_CHECK_TENANT("t.")>
order by t.record_id
limit :rowCount offset :offset
@@ -118,7 +118,7 @@ select
count(1) as count
from <tableName()> t
where t.plugin_name = :pluginName
-and t.is_active = true
+<andCheckSoftDeletionWithComma("t.")>
<AND_CHECK_TENANT("t.")>
;
>>
diff --git a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
index 52e64ac..2fc2626 100644
--- a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
+++ b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
@@ -26,15 +26,10 @@ import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeoutException;
-import org.killbill.automaton.OperationException;
-import org.killbill.billing.payment.logging.SpyLogger;
-import org.killbill.billing.payment.provider.ExternalPaymentProviderPlugin;
-import org.killbill.commons.request.Request;
-import org.killbill.commons.request.RequestData;
-
import javax.annotation.Nullable;
import org.joda.time.LocalDate;
+import org.killbill.automaton.OperationException;
import org.killbill.billing.ErrorCode;
import org.killbill.billing.account.api.Account;
import org.killbill.billing.catalog.api.Currency;
@@ -48,8 +43,11 @@ import org.killbill.billing.payment.core.sm.OperationCallbackBase;
import org.killbill.billing.payment.dao.PaymentAttemptModelDao;
import org.killbill.billing.payment.dao.PaymentSqlDao;
import org.killbill.billing.payment.invoice.InvoicePaymentControlPluginApi;
+import org.killbill.billing.payment.logging.SpyLogger;
import org.killbill.billing.payment.plugin.api.PaymentPluginStatus;
+import org.killbill.billing.payment.provider.ExternalPaymentProviderPlugin;
import org.killbill.billing.payment.provider.MockPaymentProviderPlugin;
+import org.killbill.billing.util.entity.Pagination;
import org.killbill.bus.api.PersistentBus.EventBusException;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
@@ -108,7 +106,22 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
}
}
- @Test(groups = "slow")
+ @Test(groups = "slow")
+ public void testAddRemovePaymentMethod() throws Exception {
+ final Long baseNbRecords = paymentApi.getPaymentMethods(0L, 1000L, false, ImmutableList.<PluginProperty>of(), callContext).getMaxNbRecords();
+ Assert.assertEquals(baseNbRecords, (Long) 1L);
+
+ final Account account = testHelper.createTestAccount(UUID.randomUUID().toString(), true);
+ final UUID paymentMethodId = account.getPaymentMethodId();
+
+ checkPaymentMethodPagination(paymentMethodId, baseNbRecords + 1, false);
+
+ paymentApi.deletePaymentMethod(account, paymentMethodId, true, ImmutableList.<PluginProperty>of(), callContext);
+
+ checkPaymentMethodPagination(paymentMethodId, baseNbRecords, true);
+ }
+
+ @Test(groups = "slow")
public void testCreateSuccessPurchase() throws PaymentApiException {
final BigDecimal requestedAmount = BigDecimal.TEN;
@@ -1031,4 +1044,47 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
result.add(new PluginProperty(InvoicePaymentControlPluginApi.PROP_IPCD_INVOICE_ID, invoice.getId().toString(), false));
return result;
}
+
+ // Search by a key supported by the search in MockPaymentProviderPlugin
+ private void checkPaymentMethodPagination(final UUID paymentMethodId, final Long maxNbRecords, final boolean deleted) throws PaymentApiException {
+ final Pagination<PaymentMethod> foundPaymentMethods = paymentApi.searchPaymentMethods(paymentMethodId.toString(), 0L, maxNbRecords + 1, false, ImmutableList.<PluginProperty>of(), callContext);
+ Assert.assertEquals(foundPaymentMethods.iterator().hasNext(), !deleted);
+ Assert.assertEquals(foundPaymentMethods.getMaxNbRecords(), maxNbRecords);
+ Assert.assertEquals(foundPaymentMethods.getTotalNbRecords(), (Long) (!deleted ? 1L : 0L));
+
+ final Pagination<PaymentMethod> foundPaymentMethodsWithPluginInfo = paymentApi.searchPaymentMethods(paymentMethodId.toString(), 0L, maxNbRecords + 1, true, ImmutableList.<PluginProperty>of(), callContext);
+ Assert.assertEquals(foundPaymentMethodsWithPluginInfo.iterator().hasNext(), !deleted);
+ Assert.assertEquals(foundPaymentMethodsWithPluginInfo.getMaxNbRecords(), maxNbRecords);
+ Assert.assertEquals(foundPaymentMethodsWithPluginInfo.getTotalNbRecords(), (Long) (!deleted ? 1L : 0L));
+
+ final Pagination<PaymentMethod> foundPaymentMethods2 = paymentApi.searchPaymentMethods(paymentMethodId.toString(), 0L, maxNbRecords + 1, MockPaymentProviderPlugin.PLUGIN_NAME, false, ImmutableList.<PluginProperty>of(), callContext);
+ Assert.assertEquals(foundPaymentMethods2.iterator().hasNext(), !deleted);
+ Assert.assertEquals(foundPaymentMethods2.getMaxNbRecords(), maxNbRecords);
+ Assert.assertEquals(foundPaymentMethods2.getTotalNbRecords(), (Long) (!deleted ? 1L : 0L));
+
+ final Pagination<PaymentMethod> foundPaymentMethods2WithPluginInfo = paymentApi.searchPaymentMethods(paymentMethodId.toString(), 0L, maxNbRecords + 1, MockPaymentProviderPlugin.PLUGIN_NAME, true, ImmutableList.<PluginProperty>of(), callContext);
+ Assert.assertEquals(foundPaymentMethods2WithPluginInfo.iterator().hasNext(), !deleted);
+ Assert.assertEquals(foundPaymentMethods2WithPluginInfo.getMaxNbRecords(), maxNbRecords);
+ Assert.assertEquals(foundPaymentMethods2WithPluginInfo.getTotalNbRecords(), (Long) (!deleted ? 1L : 0L));
+
+ final Pagination<PaymentMethod> gotPaymentMethods = paymentApi.getPaymentMethods(0L, maxNbRecords + 1L, false, ImmutableList.<PluginProperty>of(), callContext);
+ Assert.assertEquals(gotPaymentMethods.iterator().hasNext(), maxNbRecords > 0);
+ Assert.assertEquals(gotPaymentMethods.getMaxNbRecords(), maxNbRecords);
+ Assert.assertEquals(gotPaymentMethods.getTotalNbRecords(), maxNbRecords);
+
+ final Pagination<PaymentMethod> gotPaymentMethodsWithPluginInfo = paymentApi.getPaymentMethods(0L, maxNbRecords + 1L, true, ImmutableList.<PluginProperty>of(), callContext);
+ Assert.assertEquals(gotPaymentMethodsWithPluginInfo.iterator().hasNext(), maxNbRecords > 0);
+ Assert.assertEquals(gotPaymentMethodsWithPluginInfo.getMaxNbRecords(), maxNbRecords);
+ Assert.assertEquals(gotPaymentMethodsWithPluginInfo.getTotalNbRecords(), maxNbRecords);
+
+ final Pagination<PaymentMethod> gotPaymentMethods2 = paymentApi.getPaymentMethods(0L, maxNbRecords + 1L, MockPaymentProviderPlugin.PLUGIN_NAME, false, ImmutableList.<PluginProperty>of(), callContext);
+ Assert.assertEquals(gotPaymentMethods2.iterator().hasNext(), maxNbRecords > 0);
+ Assert.assertEquals(gotPaymentMethods2.getMaxNbRecords(), maxNbRecords);
+ Assert.assertEquals(gotPaymentMethods2.getTotalNbRecords(), maxNbRecords);
+
+ final Pagination<PaymentMethod> gotPaymentMethods2WithPluginInfo = paymentApi.getPaymentMethods(0L, maxNbRecords + 1L, MockPaymentProviderPlugin.PLUGIN_NAME, true, ImmutableList.<PluginProperty>of(), callContext);
+ Assert.assertEquals(gotPaymentMethods2WithPluginInfo.iterator().hasNext(), maxNbRecords > 0);
+ Assert.assertEquals(gotPaymentMethods2WithPluginInfo.getMaxNbRecords(), maxNbRecords);
+ Assert.assertEquals(gotPaymentMethods2WithPluginInfo.getTotalNbRecords(), maxNbRecords);
+ }
}
diff --git a/payment/src/test/java/org/killbill/billing/payment/provider/MockPaymentProviderPlugin.java b/payment/src/test/java/org/killbill/billing/payment/provider/MockPaymentProviderPlugin.java
index 537c603..8788e73 100644
--- a/payment/src/test/java/org/killbill/billing/payment/provider/MockPaymentProviderPlugin.java
+++ b/payment/src/test/java/org/killbill/billing/payment/provider/MockPaymentProviderPlugin.java
@@ -305,7 +305,7 @@ public class MockPaymentProviderPlugin implements PaymentPluginApi {
return (input.getKbPaymentMethodId().toString().equals(searchKey));
}
}));
- return DefaultPagination.<PaymentMethodPlugin>build(offset, limit, results);
+ return DefaultPagination.<PaymentMethodPlugin>build(offset, limit, paymentMethods.size(), results);
}
@Override
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java b/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
index 6aaed33..af1970f 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/engine/dao/MockSubscriptionDaoMemory.java
@@ -126,7 +126,9 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
@Override
public Pagination<SubscriptionBundleModelDao> searchSubscriptionBundles(final String searchKey, final Long offset, final Long limit, final InternalTenantContext context) {
final List<SubscriptionBundleModelDao> results = new LinkedList<SubscriptionBundleModelDao>();
+ int maxNbRecords = 0;
for (final SubscriptionBundleModelDao bundleModelDao : getAll(context)) {
+ maxNbRecords++;
if (bundleModelDao.getId().toString().equals(searchKey) ||
bundleModelDao.getExternalKey().equals(searchKey) ||
bundleModelDao.getAccountId().toString().equals(searchKey)) {
@@ -134,7 +136,7 @@ public class MockSubscriptionDaoMemory extends MockEntityDaoBase<SubscriptionBun
}
}
- return DefaultPagination.<SubscriptionBundleModelDao>build(offset, limit, results);
+ return DefaultPagination.<SubscriptionBundleModelDao>build(offset, limit, maxNbRecords, results);
}
@Override
diff --git a/util/src/main/java/org/killbill/billing/util/entity/dao/DefaultPaginationHelper.java b/util/src/main/java/org/killbill/billing/util/entity/dao/DefaultPaginationHelper.java
index 6b0c800..a417357 100644
--- a/util/src/main/java/org/killbill/billing/util/entity/dao/DefaultPaginationHelper.java
+++ b/util/src/main/java/org/killbill/billing/util/entity/dao/DefaultPaginationHelper.java
@@ -42,7 +42,7 @@ public class DefaultPaginationHelper {
public abstract Pagination<E> build(final Long offset, final Long limit, final String pluginName) throws T;
}
- public static <E extends Entity, T extends BillingExceptionBase> Pagination<E> getEntityPaginationFromPlugins(final Iterable<String> plugins, final Long offset, final Long limit, final EntityPaginationBuilder<E, T> entityPaginationBuilder) {
+ public static <E extends Entity, T extends BillingExceptionBase> Pagination<E> getEntityPaginationFromPlugins(final boolean maxStatsCrossPlugins, final Iterable<String> plugins, final Long offset, final Long limit, final EntityPaginationBuilder<E, T> entityPaginationBuilder) {
// Note that we cannot easily do streaming here, since we would have to rely on the statistics
// returned by the Pagination objects from the plugins and we probably don't want to do that (if
// one plugin gets it wrong, it may starve the others).
@@ -67,7 +67,12 @@ public class DefaultPaginationHelper {
// Make sure not to start at 0 for subsequent plugins if previous ones didn't yield any result
firstSearch = allResults.isEmpty();
totalNbRecords += pages.getTotalNbRecords();
- maxNbRecords += pages.getMaxNbRecords();
+ if (!maxStatsCrossPlugins) {
+ maxNbRecords += pages.getMaxNbRecords();
+ } else {
+ // getPayments and getPaymentMethods return MaxNbRecords across all plugins -- make sure we don't double count
+ maxNbRecords = Math.max(maxNbRecords, pages.getMaxNbRecords());
+ }
} catch (final BillingExceptionBase e) {
log.warn("Error while searching plugin " + pluginName, e);
// Non-fatal, continue to search other plugins
diff --git a/util/src/main/java/org/killbill/billing/util/entity/dao/DefaultPaginationSqlDaoHelper.java b/util/src/main/java/org/killbill/billing/util/entity/dao/DefaultPaginationSqlDaoHelper.java
index 1f9a9fd..8157d11 100644
--- a/util/src/main/java/org/killbill/billing/util/entity/dao/DefaultPaginationSqlDaoHelper.java
+++ b/util/src/main/java/org/killbill/billing/util/entity/dao/DefaultPaginationSqlDaoHelper.java
@@ -1,7 +1,9 @@
/*
* Copyright 2010-2014 Ning, Inc.
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -61,6 +63,9 @@ public class DefaultPaginationSqlDaoHelper {
public abstract static class PaginationIteratorBuilder<M extends EntityModelDao<E>, E extends Entity, S extends EntitySqlDao<M, E>> {
+ // Determine the totalNbRecords:
+ // - For search queries, return the "SearchCount", i.e. the number of records matching the search query.
+ // - For get calls, return the total number of records (totalNbRecords == maxNbRecords)
public abstract Long getCount(final S sqlDao, final InternalTenantContext context);
public abstract Iterator<M> build(final S sqlDao, final Long limit, final InternalTenantContext context);
diff --git a/util/src/main/java/org/killbill/billing/util/entity/DefaultPagination.java b/util/src/main/java/org/killbill/billing/util/entity/DefaultPagination.java
index 3abdf37..81401d6 100644
--- a/util/src/main/java/org/killbill/billing/util/entity/DefaultPagination.java
+++ b/util/src/main/java/org/killbill/billing/util/entity/DefaultPagination.java
@@ -33,9 +33,13 @@ public class DefaultPagination<T> implements Pagination<T> {
private final Long maxNbRecords;
private final Iterator<T> delegateIterator;
- // Builder when the streaming API can't be used (should only be used for tests)
+ // Builders when the streaming API can't be used (should only be used for tests)
// Notes: elements should be the entire records set (regardless of filtering) otherwise maxNbRecords won't be accurate
public static <T> Pagination<T> build(final Long offset, final Long limit, final Collection<T> elements) {
+ return build(offset, limit, elements.size(), elements);
+ }
+
+ public static <T> Pagination<T> build(final Long offset, final Long limit, final Integer maxNbRecords, final Collection<T> elements) {
final List<T> allResults = ImmutableList.<T>copyOf(elements);
final List<T> results;
@@ -46,7 +50,7 @@ public class DefaultPagination<T> implements Pagination<T> {
} else {
results = allResults.subList(offset.intValue(), offset.intValue() + limit.intValue());
}
- return new DefaultPagination<T>(offset, limit, (long) results.size(), (long) allResults.size(), results.iterator());
+ return new DefaultPagination<T>(offset, limit, (long) results.size(), (long) maxNbRecords, results.iterator());
}
// Constructor for DAO -> API bridge
diff --git a/util/src/main/resources/org/killbill/billing/util/entity/dao/EntitySqlDao.sql.stg b/util/src/main/resources/org/killbill/billing/util/entity/dao/EntitySqlDao.sql.stg
index fe9ac05..13022fe 100644
--- a/util/src/main/resources/org/killbill/billing/util/entity/dao/EntitySqlDao.sql.stg
+++ b/util/src/main/resources/org/killbill/billing/util/entity/dao/EntitySqlDao.sql.stg
@@ -268,6 +268,7 @@ select
<allTableFields("t.")>
from <tableName()> t
where (<searchQuery("t.")>)
+<andCheckSoftDeletionWithComma("t.")>
<AND_CHECK_TENANT("t.")>
order by <recordIdField("t.")> ASC
limit :rowCount offset :offset
@@ -279,6 +280,7 @@ select
count(1) as count
from <tableName()> t
where (<searchQuery("t.")>)
+<andCheckSoftDeletionWithComma("t.")>
<AND_CHECK_TENANT("t.")>
;
>>
diff --git a/util/src/main/resources/org/killbill/billing/util/tag/dao/TagSqlDao.sql.stg b/util/src/main/resources/org/killbill/billing/util/tag/dao/TagSqlDao.sql.stg
index 1b82e3c..00c7bbe 100644
--- a/util/src/main/resources/org/killbill/billing/util/tag/dao/TagSqlDao.sql.stg
+++ b/util/src/main/resources/org/killbill/billing/util/tag/dao/TagSqlDao.sql.stg
@@ -64,6 +64,7 @@ userAndSystemTagDefinitions() ::= <<
, name
, description
from tag_definitions
+ where is_active
union
select
\'00000000-0000-0000-0000-000000000001\' id
@@ -114,6 +115,7 @@ select
from <tableName()> t
join (<userAndSystemTagDefinitions()>) td on td.id = t.tag_definition_id
where (<searchQuery(tagAlias="t.", tagDefinitionAlias="td.")>)
+<andCheckSoftDeletionWithComma("t.")>
<AND_CHECK_TENANT("t.")>
order by <recordIdField("t.")> ASC
limit :rowCount offset :offset
@@ -126,6 +128,7 @@ select
from <tableName()> t
join (<userAndSystemTagDefinitions()>) td on td.id = t.tag_definition_id
where (<searchQuery(tagAlias="t.", tagDefinitionAlias="td.")>)
+<andCheckSoftDeletionWithComma("t.")>
<AND_CHECK_TENANT("t.")>
;
>>
diff --git a/util/src/test/java/org/killbill/billing/mock/api/MockAccountUserApi.java b/util/src/test/java/org/killbill/billing/mock/api/MockAccountUserApi.java
index d365b82..18e47eb 100644
--- a/util/src/test/java/org/killbill/billing/mock/api/MockAccountUserApi.java
+++ b/util/src/test/java/org/killbill/billing/mock/api/MockAccountUserApi.java
@@ -118,7 +118,7 @@ public class MockAccountUserApi implements AccountUserApi {
results.add(account);
}
}
- return DefaultPagination.<Account>build(offset, limit, results);
+ return DefaultPagination.<Account>build(offset, limit, accounts.size(), results);
}
@Override
diff --git a/util/src/test/java/org/killbill/billing/util/customfield/api/TestDefaultCustomFieldUserApi.java b/util/src/test/java/org/killbill/billing/util/customfield/api/TestDefaultCustomFieldUserApi.java
index 5a60177..92f6715 100644
--- a/util/src/test/java/org/killbill/billing/util/customfield/api/TestDefaultCustomFieldUserApi.java
+++ b/util/src/test/java/org/killbill/billing/util/customfield/api/TestDefaultCustomFieldUserApi.java
@@ -1,7 +1,9 @@
/*
- * Copyright 2010-2012 Ning, Inc.
+ * Copyright 2010-2013 Ning, Inc.
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
*
- * Ning licenses this file to you under the Apache License, version 2.0
+ * The Billing Project 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:
*
@@ -21,16 +23,16 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
-import org.skife.jdbi.v2.Handle;
-import org.skife.jdbi.v2.tweak.HandleCallback;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
import org.killbill.billing.ObjectType;
import org.killbill.billing.api.TestApiListener.NextEvent;
import org.killbill.billing.util.UtilTestSuiteWithEmbeddedDB;
import org.killbill.billing.util.customfield.CustomField;
import org.killbill.billing.util.customfield.StringCustomField;
+import org.killbill.billing.util.entity.Pagination;
+import org.skife.jdbi.v2.Handle;
+import org.skife.jdbi.v2.tweak.HandleCallback;
+import org.testng.Assert;
+import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
@@ -52,6 +54,8 @@ public class TestDefaultCustomFieldUserApi extends UtilTestSuiteWithEmbeddedDB {
}
});
+ checkPagination(0);
+
final String cfName = UUID.randomUUID().toString().substring(1, 4);
final String cfValue = UUID.randomUUID().toString().substring(1, 4);
final CustomField customField = new StringCustomField(cfName, cfValue, ObjectType.ACCOUNT, accountId, callContext.getCreatedDate());
@@ -59,6 +63,8 @@ public class TestDefaultCustomFieldUserApi extends UtilTestSuiteWithEmbeddedDB {
customFieldUserApi.addCustomFields(ImmutableList.<CustomField>of(customField), callContext);
assertListenerStatus();
+ checkPagination(1);
+
// Verify the field was saved
final List<CustomField> customFields = customFieldUserApi.getCustomFieldsForObject(accountId, ObjectType.ACCOUNT, callContext);
Assert.assertEquals(customFields.size(), 1);
@@ -82,6 +88,8 @@ public class TestDefaultCustomFieldUserApi extends UtilTestSuiteWithEmbeddedDB {
List<CustomField> remainingCustomFields = customFieldUserApi.getCustomFieldsForObject(accountId, ObjectType.ACCOUNT, callContext);
Assert.assertEquals(remainingCustomFields.size(), 0);
+ checkPagination(0);
+
// Add again the custom field
final CustomField newCustomField = new StringCustomField(cfName, cfValue, ObjectType.ACCOUNT, accountId, callContext.getCreatedDate());
@@ -90,10 +98,25 @@ public class TestDefaultCustomFieldUserApi extends UtilTestSuiteWithEmbeddedDB {
remainingCustomFields = customFieldUserApi.getCustomFieldsForObject(accountId, ObjectType.ACCOUNT, callContext);
Assert.assertEquals(remainingCustomFields.size(), 1);
+ checkPagination(1);
+
// Delete again
customFieldUserApi.removeCustomFields(remainingCustomFields, callContext);
remainingCustomFields = customFieldUserApi.getCustomFieldsForObject(accountId, ObjectType.ACCOUNT, callContext);
Assert.assertEquals(remainingCustomFields.size(), 0);
+ checkPagination(0);
+ }
+
+ private void checkPagination(final long nbRecords) {
+ final Pagination<CustomField> foundCustomFields = customFieldUserApi.searchCustomFields("ACCOUNT", 0L, nbRecords + 1L, callContext);
+ Assert.assertEquals(foundCustomFields.iterator().hasNext(), nbRecords > 0);
+ Assert.assertEquals(foundCustomFields.getMaxNbRecords(), (Long) nbRecords);
+ Assert.assertEquals(foundCustomFields.getTotalNbRecords(), (Long) nbRecords);
+
+ final Pagination<CustomField> gotCustomFields = customFieldUserApi.getCustomFields(0L, nbRecords + 1L, callContext);
+ Assert.assertEquals(gotCustomFields.iterator().hasNext(), nbRecords > 0);
+ Assert.assertEquals(gotCustomFields.getMaxNbRecords(), (Long) nbRecords);
+ Assert.assertEquals(gotCustomFields.getTotalNbRecords(), (Long) nbRecords);
}
}
diff --git a/util/src/test/java/org/killbill/billing/util/tag/api/TestDefaultTagUserApi.java b/util/src/test/java/org/killbill/billing/util/tag/api/TestDefaultTagUserApi.java
new file mode 100644
index 0000000..7042c2b
--- /dev/null
+++ b/util/src/test/java/org/killbill/billing/util/tag/api/TestDefaultTagUserApi.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2014-2015 Groupon, Inc
+ * Copyright 2014-2015 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.util.tag.api;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import org.killbill.billing.ObjectType;
+import org.killbill.billing.api.TestApiListener.NextEvent;
+import org.killbill.billing.util.UtilTestSuiteWithEmbeddedDB;
+import org.killbill.billing.util.entity.Pagination;
+import org.killbill.billing.util.tag.ControlTagType;
+import org.killbill.billing.util.tag.Tag;
+import org.skife.jdbi.v2.Handle;
+import org.skife.jdbi.v2.tweak.HandleCallback;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+
+public class TestDefaultTagUserApi extends UtilTestSuiteWithEmbeddedDB {
+
+ @Test(groups = "slow")
+ public void testSaveTagWithAccountRecordId() throws Exception {
+ final UUID accountId = UUID.randomUUID();
+ final Long accountRecordId = 19384012L;
+
+ dbi.withHandle(new HandleCallback<Void>() {
+ @Override
+ public Void withHandle(final Handle handle) throws Exception {
+ // Note: we always create an accounts table, see MysqlTestingHelper
+ handle.execute("insert into accounts (record_id, id, email, name, first_name_length, is_notified_for_invoices, created_date, created_by, updated_date, updated_by) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+ accountRecordId, accountId.toString(), "yo@t.com", "toto", 4, false, new Date(), "i", new Date(), "j");
+
+ return null;
+ }
+ });
+
+ checkPagination(0);
+
+ eventsListener.pushExpectedEvent(NextEvent.TAG);
+ tagUserApi.addTags(accountId, ObjectType.ACCOUNT, ImmutableList.<UUID>of(ControlTagType.WRITTEN_OFF.getId()), callContext);
+ assertListenerStatus();
+
+ checkPagination(1);
+
+ // Verify the tag was saved
+ final List<Tag> tags = tagUserApi.getTagsForObject(accountId, ObjectType.ACCOUNT, true, callContext);
+ Assert.assertEquals(tags.size(), 1);
+ Assert.assertEquals(tags.get(0).getTagDefinitionId(), ControlTagType.WRITTEN_OFF.getId());
+ Assert.assertEquals(tags.get(0).getObjectId(), accountId);
+ Assert.assertEquals(tags.get(0).getObjectType(), ObjectType.ACCOUNT);
+ // Verify the account_record_id was populated
+ dbi.withHandle(new HandleCallback<Void>() {
+ @Override
+ public Void withHandle(final Handle handle) throws Exception {
+ final List<Map<String, Object>> values = handle.select("select account_record_id from tags where object_id = ?", accountId.toString());
+ Assert.assertEquals(values.size(), 1);
+ Assert.assertEquals(values.get(0).keySet().size(), 1);
+ Assert.assertEquals(Long.valueOf(values.get(0).get("account_record_id").toString()), accountRecordId);
+ return null;
+ }
+ });
+
+ tagUserApi.removeTags(accountId, ObjectType.ACCOUNT, ImmutableList.<UUID>of(ControlTagType.WRITTEN_OFF.getId()), callContext);
+ List<Tag> remainingTags = tagUserApi.getTagsForObject(accountId, ObjectType.ACCOUNT, false, callContext);
+ Assert.assertEquals(remainingTags.size(), 0);
+
+ checkPagination(0);
+
+ // Add again the tag
+ eventsListener.pushExpectedEvent(NextEvent.TAG);
+ tagUserApi.addTags(accountId, ObjectType.ACCOUNT, ImmutableList.<UUID>of(ControlTagType.WRITTEN_OFF.getId()), callContext);
+ remainingTags = tagUserApi.getTagsForObject(accountId, ObjectType.ACCOUNT, false, callContext);
+ Assert.assertEquals(remainingTags.size(), 1);
+
+ checkPagination(1);
+
+ // Delete again
+ tagUserApi.removeTags(accountId, ObjectType.ACCOUNT, ImmutableList.<UUID>of(ControlTagType.WRITTEN_OFF.getId()), callContext);
+ remainingTags = tagUserApi.getTagsForObject(accountId, ObjectType.ACCOUNT, false, callContext);
+ Assert.assertEquals(remainingTags.size(), 0);
+
+ checkPagination(0);
+ }
+
+ private void checkPagination(final long nbRecords) {
+ final Pagination<Tag> foundTags = tagUserApi.searchTags("ACCOUNT", 0L, nbRecords + 1L, callContext);
+ Assert.assertEquals(foundTags.iterator().hasNext(), nbRecords > 0);
+ Assert.assertEquals(foundTags.getMaxNbRecords(), (Long) nbRecords);
+ Assert.assertEquals(foundTags.getTotalNbRecords(), (Long) nbRecords);
+
+ final Pagination<Tag> gotTags = tagUserApi.getTags(0L, nbRecords + 1L, callContext);
+ Assert.assertEquals(gotTags.iterator().hasNext(), nbRecords > 0);
+ Assert.assertEquals(gotTags.getMaxNbRecords(), (Long) nbRecords);
+ Assert.assertEquals(gotTags.getTotalNbRecords(), (Long) nbRecords);
+ }
+}
diff --git a/util/src/test/java/org/killbill/billing/util/UtilTestSuiteWithEmbeddedDB.java b/util/src/test/java/org/killbill/billing/util/UtilTestSuiteWithEmbeddedDB.java
index 5e15c74..5317d3f 100644
--- a/util/src/test/java/org/killbill/billing/util/UtilTestSuiteWithEmbeddedDB.java
+++ b/util/src/test/java/org/killbill/billing/util/UtilTestSuiteWithEmbeddedDB.java
@@ -33,6 +33,7 @@ import org.killbill.billing.util.dao.NonEntityDao;
import org.killbill.billing.util.export.dao.DatabaseExportDao;
import org.killbill.billing.util.glue.TestUtilModuleWithEmbeddedDB;
import org.killbill.billing.util.nodes.dao.NodeInfoDao;
+import org.killbill.billing.util.tag.api.DefaultTagUserApi;
import org.killbill.billing.util.tag.dao.DefaultTagDao;
import org.killbill.billing.util.tag.dao.TagDefinitionDao;
import org.killbill.bus.api.PersistentBus;
@@ -65,6 +66,8 @@ public abstract class UtilTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuite
@Inject
protected InternalCallContextFactory internalCallContextFactory;
@Inject
+ protected DefaultTagUserApi tagUserApi;
+ @Inject
protected DefaultCustomFieldUserApi customFieldUserApi;
@Inject
protected CustomFieldDao customFieldDao;