killbill-aplcache
Changes
util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogsForObjectType.java 151(+151 -0)
Details
diff --git a/beatrix/src/test/java/com/ning/billing/beatrix/util/AuditChecker.java b/beatrix/src/test/java/com/ning/billing/beatrix/util/AuditChecker.java
index 1099bf6..53cab7f 100644
--- a/beatrix/src/test/java/com/ning/billing/beatrix/util/AuditChecker.java
+++ b/beatrix/src/test/java/com/ning/billing/beatrix/util/AuditChecker.java
@@ -16,7 +16,6 @@
package com.ning.billing.beatrix.util;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.UUID;
@@ -46,14 +45,12 @@ import com.ning.billing.subscription.engine.dao.SubscriptionEventSqlDao;
import com.ning.billing.subscription.engine.dao.SubscriptionSqlDao;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.api.AuditUserApi;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.ning.billing.util.audit.AuditLog;
-import com.ning.billing.util.audit.AuditLogsForAccount;
-import com.ning.billing.util.audit.AuditLogsForBundles;
-import com.ning.billing.util.audit.AuditLogsForInvoices;
-import com.ning.billing.util.audit.AuditLogsForPayments;
import com.ning.billing.util.audit.ChangeType;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.InternalCallContextFactory;
+import com.ning.billing.util.callcontext.TenantContext;
import com.ning.billing.util.dao.NonEntityDao;
import com.ning.billing.util.entity.Entity;
import com.ning.billing.util.entity.dao.EntityModelDao;
@@ -85,15 +82,14 @@ public class AuditChecker {
*/
public void checkAccountCreated(final Account account, final CallContext context) {
- AuditLogsForAccount result = auditUserApi.getAuditLogsForAccount(account.getId(), AuditLevel.FULL, context);
- checkAuditLog(ChangeType.INSERT, context, result.getAccountAuditLogs().get(0), account.getId(), AccountSqlDao.class, true, true);
- checkAuditLog(ChangeType.UPDATE, context, result.getAccountAuditLogs().get(1), account.getId(), AccountSqlDao.class, true, true);
+ final AccountAuditLogs result = auditUserApi.getAccountAuditLogs(account.getId(), AuditLevel.FULL, context);
+ checkAuditLog(ChangeType.INSERT, context, result.getAuditLogsForAccount().get(0), account.getId(), AccountSqlDao.class, true, true);
+ checkAuditLog(ChangeType.UPDATE, context, result.getAuditLogsForAccount().get(1), account.getId(), AccountSqlDao.class, true, true);
}
public void checkPaymentCreated(final Payment payment, final CallContext context) {
- AuditLogsForPayments result = getAuditLogsForPayment(payment, context);
- Assert.assertEquals(result.getPaymentsAuditLogs().size(), 1);
- final List<AuditLog> paymentLogs = result.getPaymentsAuditLogs().get(payment.getId());
+ final AccountAuditLogs result = auditUserApi.getAccountAuditLogs(payment.getAccountId(), AuditLevel.FULL, context);
+ final List<AuditLog> paymentLogs = result.getAuditLogsForPayment(payment.getId());
Assert.assertEquals(paymentLogs.size(), 2);
checkAuditLog(ChangeType.INSERT, context, paymentLogs.get(0), payment.getId(), PaymentSqlDao.class, true, false);
checkAuditLog(ChangeType.UPDATE, context, paymentLogs.get(1), payment.getId(), PaymentSqlDao.class, true, false);
@@ -105,16 +101,16 @@ public class AuditChecker {
// Pass the call callcontext used to create the bundle
public void checkBundleCreated(final UUID bundleId, final CallContext context) {
- final AuditLogsForBundles auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
- Assert.assertEquals(auditLogsForBundles.getBundlesAuditLogs().keySet().size(), 1);
- checkAuditLog(ChangeType.INSERT, context, auditLogsForBundles.getBundlesAuditLogs().get(bundleId).get(0), bundleId, BundleSqlDao.class, false, false);
+ final List<AuditLog> auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
+ Assert.assertEquals(auditLogsForBundles.size(), 1);
+ checkAuditLog(ChangeType.INSERT, context, auditLogsForBundles.get(0), bundleId, BundleSqlDao.class, false, false);
}
// Pass the call callcontext used to update the bundle
public void checkBundleUpdated(final UUID bundleId, final CallContext context) {
- final AuditLogsForBundles auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
- Assert.assertEquals(auditLogsForBundles.getBundlesAuditLogs().keySet().size(), 1);
- checkAuditLog(ChangeType.UPDATE, context, auditLogsForBundles.getBundlesAuditLogs().get(bundleId).get(auditLogsForBundles.getBundlesAuditLogs().get(bundleId).size() - 1), bundleId, BundleSqlDao.class, false, false);
+ final List<AuditLog> auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
+ Assert.assertTrue(auditLogsForBundles.size() > 1);
+ checkAuditLog(ChangeType.UPDATE, context, auditLogsForBundles.get(auditLogsForBundles.size() - 1), bundleId, BundleSqlDao.class, false, false);
}
/**
@@ -123,19 +119,17 @@ public class AuditChecker {
// Pass the call callcontext used to create the subscription
public void checkSubscriptionCreated(final UUID bundleId, final UUID subscriptionId, final CallContext context) {
- final AuditLogsForBundles auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
- Assert.assertEquals(auditLogsForBundles.getSubscriptionsAuditLogs().keySet().size(), 1);
- checkAuditLog(ChangeType.INSERT, context, auditLogsForBundles.getSubscriptionsAuditLogs().get(subscriptionId).get(0), subscriptionId, SubscriptionSqlDao.class, false, true);
+ final List<AuditLog> auditLogsForSubscription = getAuditLogsForSubscription(bundleId, subscriptionId, context);
+ Assert.assertEquals(auditLogsForSubscription.size(), 1);
+ checkAuditLog(ChangeType.INSERT, context, auditLogsForSubscription.get(0), subscriptionId, SubscriptionSqlDao.class, false, true);
}
// Pass the call callcontext used to update the subscription
public void checkSubscriptionUpdated(final UUID bundleId, final UUID subscriptionId, final CallContext context) {
- final AuditLogsForBundles auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
-
- Assert.assertEquals(auditLogsForBundles.getSubscriptionsAuditLogs().keySet().size(), 1);
- Assert.assertEquals(auditLogsForBundles.getSubscriptionsAuditLogs().get(subscriptionId).size(), 2);
- checkAuditLog(ChangeType.INSERT, auditLogsForBundles.getSubscriptionsAuditLogs().get(subscriptionId).get(0));
- checkAuditLog(ChangeType.UPDATE, context, auditLogsForBundles.getSubscriptionsAuditLogs().get(subscriptionId).get(1), subscriptionId, SubscriptionSqlDao.class, false, false);
+ final List<AuditLog> auditLogsForSubscription = getAuditLogsForSubscription(bundleId, subscriptionId, context);
+ Assert.assertEquals(auditLogsForSubscription.size(), 2);
+ checkAuditLog(ChangeType.INSERT, auditLogsForSubscription.get(0));
+ checkAuditLog(ChangeType.UPDATE, context, auditLogsForSubscription.get(1), subscriptionId, SubscriptionSqlDao.class, false, false);
}
/**
@@ -144,24 +138,17 @@ public class AuditChecker {
// Pass the call callcontext used to create the subscription event
public void checkSubscriptionEventCreated(final UUID bundleId, final UUID subscriptionEventId, final CallContext context) {
- final AuditLogsForBundles auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
- checkAuditLog(ChangeType.INSERT, context, auditLogsForBundles.getSubscriptionEventsAuditLogs().get(subscriptionEventId).get(0), subscriptionEventId, SubscriptionEventSqlDao.class, false, true);
+ final List<AuditLog> auditLogsForSubscriptionEvent = getAuditLogsForSubscriptionEvent(bundleId, subscriptionEventId, context);
+ Assert.assertEquals(auditLogsForSubscriptionEvent.size(), 1);
+ checkAuditLog(ChangeType.INSERT, context, auditLogsForSubscriptionEvent.get(0), subscriptionEventId, SubscriptionEventSqlDao.class, false, true);
}
// Pass the call callcontext used to update the subscription event
public void checkSubscriptionEventUpdated(final UUID bundleId, final UUID subscriptionEventId, final CallContext context) {
- final AuditLogsForBundles auditLogsForBundles = getAuditLogsForBundle(bundleId, context);
- checkAuditLog(ChangeType.INSERT, auditLogsForBundles.getSubscriptionEventsAuditLogs().get(subscriptionEventId).get(0));
- checkAuditLog(ChangeType.UPDATE, context, auditLogsForBundles.getSubscriptionEventsAuditLogs().get(subscriptionEventId).get(1), subscriptionEventId, SubscriptionEventSqlDao.class, false, true);
- }
-
- /**
- * ******************************************** PAYMENT *******************************************************
- */
-
- private AuditLogsForPayments getAuditLogsForPayment(final Payment payment, final CallContext context) {
- AuditLogsForPayments results = auditUserApi.getAuditLogsForPayments(Collections.singletonList(payment), AuditLevel.FULL, context);
- return results;
+ final List<AuditLog> auditLogsForSubscriptionEvent = getAuditLogsForSubscriptionEvent(bundleId, subscriptionEventId, context);
+ Assert.assertEquals(auditLogsForSubscriptionEvent.size(), 2);
+ checkAuditLog(ChangeType.INSERT, auditLogsForSubscriptionEvent.get(0));
+ checkAuditLog(ChangeType.UPDATE, context, auditLogsForSubscriptionEvent.get(1), subscriptionEventId, SubscriptionEventSqlDao.class, false, true);
}
/**
@@ -169,32 +156,53 @@ public class AuditChecker {
*/
public void checkInvoiceCreated(final Invoice invoice, final CallContext context) {
- AuditLogsForInvoices result = getAuditLogForInvoice(invoice, context);
- Assert.assertEquals(result.getInvoiceAuditLogs().keySet().size(), 1);
- final List<AuditLog> invoiceLogs = result.getInvoiceAuditLogs().get(invoice.getId());
+ final List<AuditLog> invoiceLogs = getAuditLogForInvoice(invoice, context);
Assert.assertEquals(invoiceLogs.size(), 1);
checkAuditLog(ChangeType.INSERT, context, invoiceLogs.get(0), invoice.getId(), InvoiceSqlDao.class, false, false);
- Assert.assertEquals(result.getInvoiceItemsAuditLogs().keySet().size(), invoice.getInvoiceItems().size());
for (InvoiceItem cur : invoice.getInvoiceItems()) {
- final List<AuditLog> auditLogs = result.getInvoiceItemsAuditLogs().get(cur.getId());
+ final List<AuditLog> auditLogs = getAuditLogForInvoiceItem(cur, context);
Assert.assertEquals(auditLogs.size(), 1);
checkAuditLog(ChangeType.INSERT, context, auditLogs.get(0), cur.getId(), InvoiceItemSqlDao.class, false, false);
}
}
- private AuditLogsForBundles getAuditLogsForBundle(final UUID bundleId, final CallContext context) {
+ private List<AuditLog> getAuditLogsForBundle(final UUID bundleId, final TenantContext context) {
+ try {
+ final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(bundleId, context);
+ return auditUserApi.getAccountAuditLogs(bundle.getAccountId(), AuditLevel.FULL, context).getAuditLogsForBundle(bundle.getId());
+ } catch (final SubscriptionApiException e) {
+ Assert.fail(e.toString());
+ return null;
+ }
+ }
+
+ private List<AuditLog> getAuditLogsForSubscription(final UUID bundleId, final UUID subscriptionId, final TenantContext context) {
try {
final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(bundleId, context);
- return auditUserApi.getAuditLogsForBundles(Collections.singletonList(bundle), AuditLevel.FULL, context);
- } catch (SubscriptionApiException e) {
+ return auditUserApi.getAccountAuditLogs(bundle.getAccountId(), AuditLevel.FULL, context).getAuditLogsForSubscription(subscriptionId);
+ } catch (final SubscriptionApiException e) {
Assert.fail(e.toString());
return null;
}
}
- private AuditLogsForInvoices getAuditLogForInvoice(final Invoice invoice, final CallContext context) {
- return auditUserApi.getAuditLogsForInvoices(Collections.singletonList(invoice), AuditLevel.FULL, context);
+ private List<AuditLog> getAuditLogsForSubscriptionEvent(final UUID bundleId, final UUID subscriptionEventId, final TenantContext context) {
+ try {
+ final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(bundleId, context);
+ return auditUserApi.getAccountAuditLogs(bundle.getAccountId(), AuditLevel.FULL, context).getAuditLogsForSubscriptionEvent(subscriptionEventId);
+ } catch (final SubscriptionApiException e) {
+ Assert.fail(e.toString());
+ return null;
+ }
+ }
+
+ private List<AuditLog> getAuditLogForInvoice(final Invoice invoice, final TenantContext context) {
+ return auditUserApi.getAccountAuditLogs(invoice.getAccountId(), AuditLevel.FULL, context).getAuditLogsForInvoice(invoice.getId());
+ }
+
+ private List<AuditLog> getAuditLogForInvoiceItem(final InvoiceItem invoiceItem, final TenantContext context) {
+ return auditUserApi.getAccountAuditLogs(invoiceItem.getAccountId(), AuditLevel.FULL, context).getAuditLogsForInvoiceItem(invoiceItem.getId());
}
private void checkAuditLog(final ChangeType insert, final AuditLog auditLog) {
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java
index e408af4..21507b8 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/AccountTimelineJson.java
@@ -20,12 +20,9 @@ import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import java.util.Set;
import java.util.UUID;
-import javax.annotation.Nullable;
-
import com.ning.billing.account.api.Account;
import com.ning.billing.entitlement.api.SubscriptionBundle;
import com.ning.billing.invoice.api.Invoice;
@@ -34,16 +31,11 @@ import com.ning.billing.invoice.api.InvoiceItemType;
import com.ning.billing.invoice.api.InvoicePayment;
import com.ning.billing.payment.api.Payment;
import com.ning.billing.payment.api.Refund;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.ning.billing.util.audit.AuditLog;
-import com.ning.billing.util.audit.AuditLogsForBundles;
-import com.ning.billing.util.audit.AuditLogsForInvoicePayments;
-import com.ning.billing.util.audit.AuditLogsForInvoices;
-import com.ning.billing.util.audit.AuditLogsForPayments;
-import com.ning.billing.util.audit.AuditLogsForRefunds;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
-import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
public class AccountTimelineJson {
@@ -95,35 +87,14 @@ public class AccountTimelineJson {
return tmp.toString();
}
-
public AccountTimelineJson(final Account account, final List<Invoice> invoices, final List<Payment> payments,
- final List<SubscriptionBundle> bundlesTimeline, final Multimap<UUID, Refund> refundsByPayment,
- final Multimap<UUID, InvoicePayment> chargebacksByPayment, @Nullable final AuditLogsForInvoices invoicesAuditLogs,
- @Nullable final AuditLogsForPayments paymentsAuditLogs, @Nullable final AuditLogsForRefunds refundsAuditLogs,
- @Nullable final AuditLogsForInvoicePayments chargebacksAuditLogs, @Nullable final AuditLogsForBundles bundlesAuditLogs) {
- this(account, invoices, payments, bundlesTimeline, refundsByPayment, chargebacksByPayment,
- invoicesAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : invoicesAuditLogs.getInvoiceAuditLogs(),
- invoicesAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : invoicesAuditLogs.getInvoiceItemsAuditLogs(),
- paymentsAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : paymentsAuditLogs.getPaymentsAuditLogs(),
- refundsAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : refundsAuditLogs.getRefundsAuditLogs(),
- chargebacksAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : chargebacksAuditLogs.getInvoicePaymentsAuditLogs(),
- bundlesAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : bundlesAuditLogs.getBundlesAuditLogs(),
- bundlesAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : bundlesAuditLogs.getSubscriptionsAuditLogs(),
- bundlesAuditLogs == null ? ImmutableMap.<UUID, List<AuditLog>>of() : bundlesAuditLogs.getSubscriptionEventsAuditLogs());
- }
-
- public AccountTimelineJson(final Account account, final List<Invoice> invoices, final List<Payment> payments, final List<SubscriptionBundle> bundles,
- final Multimap<UUID, Refund> refundsByPayment, final Multimap<UUID, InvoicePayment> chargebacksByPayment,
- final Map<UUID, List<AuditLog>> invoiceAuditLogs, final Map<UUID, List<AuditLog>> invoiceItemsAuditLogs,
- final Map<UUID, List<AuditLog>> paymentsAuditLogs, final Map<UUID, List<AuditLog>> refundsAuditLogs,
- final Map<UUID, List<AuditLog>> chargebacksAuditLogs, final Map<UUID, List<AuditLog>> bundlesAuditLogs,
- final Map<UUID, List<AuditLog>> subscriptionsAuditLogs, final Map<UUID, List<AuditLog>> subscriptionEventsAuditLogs) {
+ final List<SubscriptionBundle> bundles, final Multimap<UUID, Refund> refundsByPayment,
+ final Multimap<UUID, InvoicePayment> chargebacksByPayment, final AccountAuditLogs accountAuditLogs) {
this.account = new AccountJson(account, null, null);
this.bundles = new LinkedList<BundleJson>();
for (final SubscriptionBundle bundle : bundles) {
- final List<AuditLog> bundleAuditLogs = bundlesAuditLogs.get(bundle.getId());
- final BundleJson jsonWithSubscriptions = new BundleJson(bundle, bundleAuditLogs,
- subscriptionsAuditLogs, subscriptionEventsAuditLogs);
+ final List<AuditLog> bundleAuditLogs = accountAuditLogs.getAuditLogsForBundle(bundle.getId());
+ final BundleJson jsonWithSubscriptions = new BundleJson(bundle, accountAuditLogs);
this.bundles.add(jsonWithSubscriptions);
}
@@ -133,43 +104,41 @@ public class AccountTimelineJson {
for (final Invoice invoice : invoices) {
for (final InvoiceItem invoiceItem : invoice.getInvoiceItems()) {
if (InvoiceItemType.CREDIT_ADJ.equals(invoiceItem.getInvoiceItemType())) {
- final List<AuditLog> auditLogs = invoiceItemsAuditLogs.get(invoiceItem.getId());
+ final List<AuditLog> auditLogs = accountAuditLogs.getAuditLogsForInvoiceItem(invoiceItem.getId());
credits.add(new CreditJson(invoice, invoiceItem, auditLogs));
}
}
}
// Create now the invoice json objects
for (final Invoice invoice : invoices) {
- final List<AuditLog> auditLogs = invoiceAuditLogs.get(invoice.getId());
+ final List<AuditLog> auditLogs = accountAuditLogs.getAuditLogsForInvoice(invoice.getId());
this.invoices.add(new InvoiceJson(invoice,
- getBundleExternalKey(invoice, bundles),
- credits,
- auditLogs));
+ getBundleExternalKey(invoice, bundles),
+ credits,
+ auditLogs));
}
this.payments = new LinkedList<PaymentJson>();
for (final Payment payment : payments) {
final List<RefundJson> refunds = new ArrayList<RefundJson>();
for (final Refund refund : refundsByPayment.get(payment.getId())) {
- final List<AuditLog> auditLogs = refundsAuditLogs.get(refund.getId());
+ final List<AuditLog> auditLogs = accountAuditLogs.getAuditLogsForRefund(refund.getId());
// TODO add adjusted invoice items?
refunds.add(new RefundJson(refund, null, auditLogs));
}
final List<ChargebackJson> chargebacks = new ArrayList<ChargebackJson>();
for (final InvoicePayment chargeback : chargebacksByPayment.get(payment.getId())) {
- final List<AuditLog> auditLogs = chargebacksAuditLogs.get(chargeback.getId());
+ final List<AuditLog> auditLogs = accountAuditLogs.getAuditLogsForChargeback(chargeback.getId());
chargebacks.add(new ChargebackJson(payment.getAccountId(), chargeback, auditLogs));
}
- final int nbOfPaymentAttempts = payment.getAttempts().size();
- final String status = payment.getPaymentStatus().toString();
- final List<AuditLog> auditLogs = paymentsAuditLogs.get(payment.getId());
+ final List<AuditLog> auditLogs = accountAuditLogs.getAuditLogsForPayment(payment.getId());
this.payments.add(new PaymentJson(payment,
getBundleExternalKey(payment.getInvoiceId(), invoices, bundles),
refunds,
- chargebacks,
- auditLogs));
+ chargebacks,
+ auditLogs));
}
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJson.java
index da1a3e8..c3cae9c 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/BundleJson.java
@@ -18,15 +18,13 @@ package com.ning.billing.jaxrs.json;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
-import java.util.UUID;
import javax.annotation.Nullable;
import com.ning.billing.entitlement.api.Subscription;
import com.ning.billing.entitlement.api.SubscriptionBundle;
import com.ning.billing.entitlement.api.SubscriptionEvent;
-import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -71,26 +69,21 @@ public class BundleJson extends JsonBase {
return externalKey;
}
- public BundleJson(final SubscriptionBundle bundle, final List<AuditLog> auditLogs,
- final Map<UUID, List<AuditLog>> subscriptionsAuditLogs, final Map<UUID, List<AuditLog>> subscriptionEventsAuditLogs) {
- super(toAuditLogJson(auditLogs));
+ public BundleJson(final SubscriptionBundle bundle, @Nullable final AccountAuditLogs accountAuditLogs) {
+ super(toAuditLogJson(accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForBundle(bundle.getId())));
this.accountId = bundle.getAccountId().toString();
this.bundleId = bundle.getId().toString();
this.externalKey = bundle.getExternalKey();
this.subscriptions = new LinkedList<SubscriptionJson>();
for (final Subscription cur : bundle.getSubscriptions()) {
-
final ImmutableList<SubscriptionEvent> events = ImmutableList.<SubscriptionEvent>copyOf(Collections2.filter(bundle.getTimeline().getSubscriptionEvents(), new Predicate<SubscriptionEvent>() {
@Override
public boolean apply(@Nullable final SubscriptionEvent input) {
return input.getEntitlementId().equals(cur.getId());
}
}));
- this.subscriptions.add(new SubscriptionJson(cur,
- events,
- (subscriptionsAuditLogs != null ? subscriptionsAuditLogs.get(cur.getId()) : null),
- subscriptionEventsAuditLogs));
+ this.subscriptions.add(new SubscriptionJson(cur, events, accountAuditLogs));
}
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java
index 3958225..f142361 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/InvoiceJson.java
@@ -19,8 +19,6 @@ package com.ning.billing.jaxrs.json;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
-import java.util.UUID;
import javax.annotation.Nullable;
@@ -28,6 +26,7 @@ import org.joda.time.LocalDate;
import com.ning.billing.invoice.api.Invoice;
import com.ning.billing.invoice.api.InvoiceItem;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.ning.billing.util.audit.AuditLog;
import com.fasterxml.jackson.annotation.JsonCreator;
@@ -80,6 +79,9 @@ public class InvoiceJson extends JsonBase {
this.items = items;
}
+ public InvoiceJson(final Invoice input) {
+ this(input, null, null, null);
+ }
public InvoiceJson(final Invoice input, @Nullable final List<AuditLog> auditLogs) {
this(input, null, null, auditLogs);
@@ -91,11 +93,11 @@ public class InvoiceJson extends JsonBase {
input.getBalance(), input.getAccountId().toString(), bundleKeys, credits, null, toAuditLogJson(auditLogs));
}
- public InvoiceJson(final Invoice input, @Nullable final List<AuditLog> invoiceAuditLogs, @Nullable final Map<UUID, List<AuditLog>> invoiceItemsAuditLogs) {
- super(toAuditLogJson(invoiceAuditLogs));
+ public InvoiceJson(final Invoice input, final AccountAuditLogs accountAuditLogs) {
+ super(toAuditLogJson(accountAuditLogs.getAuditLogsForInvoice(input.getId())));
this.items = new ArrayList<InvoiceItemJson>(input.getInvoiceItems().size());
for (final InvoiceItem item : input.getInvoiceItems()) {
- this.items.add(new InvoiceItemJson(item, invoiceItemsAuditLogs == null ? null : invoiceItemsAuditLogs.get(item.getId())));
+ this.items.add(new InvoiceItemJson(item, accountAuditLogs.getAuditLogsForInvoiceItem(item.getId())));
}
this.amount = input.getChargedAmount();
this.currency = input.getCurrency().toString();
@@ -199,7 +201,7 @@ public class InvoiceJson extends JsonBase {
if (amount != null ? amount.compareTo(that.amount) != 0 : that.amount != null) {
return false;
}
- if (balance != null ? balance.compareTo(that.balance) != 0: that.balance != null) {
+ if (balance != null ? balance.compareTo(that.balance) != 0 : that.balance != null) {
return false;
}
if (bundleKeys != null ? !bundleKeys.equals(that.bundleKeys) : that.bundleKeys != null) {
@@ -226,7 +228,7 @@ public class InvoiceJson extends JsonBase {
if (items != null ? !items.equals(that.items) : that.items != null) {
return false;
}
- if (refundAdj != null ? refundAdj.compareTo(that.refundAdj) != 0: that.refundAdj != null) {
+ if (refundAdj != null ? refundAdj.compareTo(that.refundAdj) != 0 : that.refundAdj != null) {
return false;
}
if (targetDate != null ? targetDate.compareTo(that.targetDate) != 0 : that.targetDate != null) {
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java
index ad23683..dfaca55 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/json/SubscriptionJson.java
@@ -18,8 +18,6 @@ package com.ning.billing.jaxrs.json;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
-import java.util.UUID;
import javax.annotation.Nullable;
@@ -31,7 +29,7 @@ import com.ning.billing.catalog.api.PriceList;
import com.ning.billing.catalog.api.Product;
import com.ning.billing.entitlement.api.Subscription;
import com.ning.billing.entitlement.api.SubscriptionEvent;
-import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
@@ -313,12 +311,10 @@ public class SubscriptionJson extends JsonBase {
this.newEvents = newEvents;
}
-
public SubscriptionJson(final Subscription subscription,
final List<SubscriptionEvent> subscriptionEvents,
- final List<AuditLog> subscriptionAuditLogs,
- final Map<UUID, List<AuditLog>> subscriptionEventsAuditLogs) {
- super(toAuditLogJson(subscriptionAuditLogs));
+ @Nullable final AccountAuditLogs accountAuditLogs) {
+ super(toAuditLogJson(accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForSubscription(subscription.getId())));
this.startDate = subscription.getEffectiveStartDate();
this.productName = subscription.getLastActiveProduct().getName();
this.productCategory = subscription.getLastActiveProductCategory().name();
@@ -334,20 +330,20 @@ public class SubscriptionJson extends JsonBase {
this.externalKey = subscription.getExternalKey();
this.events = subscriptionEvents != null ? new LinkedList<EventSubscriptionJson>() : null;
if (events != null) {
- for (SubscriptionEvent cur : subscriptionEvents) {
+ for (final SubscriptionEvent cur : subscriptionEvents) {
final BillingPeriod billingPeriod = cur.getNextBillingPeriod() != null ? cur.getNextBillingPeriod() : cur.getPrevBillingPeriod();
final Product product = cur.getNextProduct() != null ? cur.getNextProduct() : cur.getPrevProduct();
final PriceList priceList = cur.getNextPriceList() != null ? cur.getNextPriceList() : cur.getPrevPriceList();
final PlanPhase phase = cur.getNextPhase() != null ? cur.getNextPhase() : cur.getPrevPhase();
this.events.add(new EventSubscriptionJson(cur.getId().toString(),
- billingPeriod != null ? billingPeriod.toString() : null,
- cur.getRequestedDate(),
- cur.getEffectiveDate(),
- product != null ? product.getName() : null,
- priceList != null ? priceList.getName() : null,
- cur.getSubscriptionEventType().toString(),
- phase != null ? phase.getName() : null,
- (subscriptionEventsAuditLogs != null ? toAuditLogJson(subscriptionEventsAuditLogs.get(cur.getId())) : null)));
+ billingPeriod != null ? billingPeriod.toString() : null,
+ cur.getRequestedDate(),
+ cur.getEffectiveDate(),
+ product != null ? product.getName() : null,
+ priceList != null ? priceList.getName() : null,
+ cur.getSubscriptionEventType().toString(),
+ phase != null ? phase.getName() : null,
+ toAuditLogJson(accountAuditLogs == null ? null : accountAuditLogs.getAuditLogsForSubscriptionEvent(cur.getId()))));
}
}
this.newEvents = null;
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
index a48b849..0cca7e0 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/AccountResource.java
@@ -90,11 +90,7 @@ import com.ning.billing.util.api.CustomFieldUserApi;
import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.api.TagUserApi;
-import com.ning.billing.util.audit.AuditLogsForBundles;
-import com.ning.billing.util.audit.AuditLogsForInvoicePayments;
-import com.ning.billing.util.audit.AuditLogsForInvoices;
-import com.ning.billing.util.audit.AuditLogsForPayments;
-import com.ning.billing.util.audit.AuditLogsForRefunds;
+import com.ning.billing.util.audit.AccountAuditLogs;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.TenantContext;
import com.ning.billing.util.entity.Pagination;
@@ -231,7 +227,7 @@ public class AccountResource extends JaxRsResourceBase {
final Collection<BundleJson> result = Collections2.transform(bundles, new Function<SubscriptionBundle, BundleJson>() {
@Override
public BundleJson apply(final SubscriptionBundle input) {
- return new BundleJson(input, null, null, null);
+ return new BundleJson(input, null);
}
});
return Response.status(Status.OK).entity(result).build();
@@ -322,15 +318,12 @@ public class AccountResource extends JaxRsResourceBase {
// Get the invoices
final List<Invoice> invoices = invoiceApi.getInvoicesByAccount(account.getId(), tenantContext);
- final AuditLogsForInvoices invoicesAuditLogs = auditUserApi.getAuditLogsForInvoices(invoices, auditMode.getLevel(), tenantContext);
// Get the payments
final List<Payment> payments = paymentApi.getAccountPayments(accountId, tenantContext);
- final AuditLogsForPayments paymentsAuditLogs = auditUserApi.getAuditLogsForPayments(payments, auditMode.getLevel(), tenantContext);
// Get the refunds
final List<Refund> refunds = paymentApi.getAccountRefunds(account, tenantContext);
- final AuditLogsForRefunds refundsAuditLogs = auditUserApi.getAuditLogsForRefunds(refunds, auditMode.getLevel(), tenantContext);
final Multimap<UUID, Refund> refundsByPayment = ArrayListMultimap.<UUID, Refund>create();
for (final Refund refund : refunds) {
refundsByPayment.put(refund.getPaymentId(), refund);
@@ -338,7 +331,6 @@ public class AccountResource extends JaxRsResourceBase {
// Get the chargebacks
final List<InvoicePayment> chargebacks = invoicePaymentApi.getChargebacksByAccountId(accountId, tenantContext);
- final AuditLogsForInvoicePayments chargebacksAuditLogs = auditUserApi.getAuditLogsForInvoicePayments(chargebacks, auditMode.getLevel(), tenantContext);
final Multimap<UUID, InvoicePayment> chargebacksByPayment = ArrayListMultimap.<UUID, InvoicePayment>create();
for (final InvoicePayment chargeback : chargebacks) {
chargebacksByPayment.put(chargeback.getPaymentId(), chargeback);
@@ -346,12 +338,13 @@ public class AccountResource extends JaxRsResourceBase {
// Get the bundles
final List<SubscriptionBundle> bundles = subscriptionApi.getSubscriptionBundlesForAccountId(account.getId(), tenantContext);
- final AuditLogsForBundles bundlesAuditLogs = auditUserApi.getAuditLogsForBundles(bundles, auditMode.getLevel(), tenantContext);
+
+ // Get all audit logs
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(accountId, auditMode.getLevel(), tenantContext);
final AccountTimelineJson json = new AccountTimelineJson(account, invoices, payments, bundles,
refundsByPayment, chargebacksByPayment,
- invoicesAuditLogs, paymentsAuditLogs, refundsAuditLogs,
- chargebacksAuditLogs, bundlesAuditLogs);
+ accountAuditLogs);
return Response.status(Status.OK).entity(json).build();
}
@@ -420,7 +413,7 @@ public class AccountResource extends JaxRsResourceBase {
@GET
@Path("/{accountId:" + UUID_PATTERN + "}/" + INVOICES)
@Produces(APPLICATION_JSON)
- public Response getInvoices(@PathParam("accountId") final String accountId,
+ public Response getInvoices(@PathParam("accountId") final String accountIdString,
@QueryParam(QUERY_INVOICE_WITH_ITEMS) @DefaultValue("false") final boolean withItems,
@QueryParam(QUERY_UNPAID_INVOICES_ONLY) @DefaultValue("false") final boolean unpaidInvoicesOnly,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@@ -428,28 +421,26 @@ public class AccountResource extends JaxRsResourceBase {
final TenantContext tenantContext = context.createContext(request);
// Verify the account exists
- accountUserApi.getAccountById(UUID.fromString(accountId), tenantContext);
+ final UUID accountId = UUID.fromString(accountIdString);
+ accountUserApi.getAccountById(accountId, tenantContext);
final List<Invoice> invoices = unpaidInvoicesOnly ?
- new ArrayList<Invoice>(invoiceApi.getUnpaidInvoicesByAccountId(UUID.fromString(accountId), null, tenantContext)) :
- invoiceApi.getInvoicesByAccount(UUID.fromString(accountId), tenantContext);
+ new ArrayList<Invoice>(invoiceApi.getUnpaidInvoicesByAccountId(accountId, null, tenantContext)) :
+ invoiceApi.getInvoicesByAccount(accountId, tenantContext);
- final AuditLogsForInvoices invoicesAuditLogs = auditUserApi.getAuditLogsForInvoices(invoices, auditMode.getLevel(), tenantContext);
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(accountId, auditMode.getLevel(), tenantContext);
if (withItems) {
final List<InvoiceJson> result = new LinkedList<InvoiceJson>();
for (final Invoice invoice : invoices) {
- result.add(new InvoiceJson(invoice,
- invoicesAuditLogs.getInvoiceAuditLogs().get(invoice.getId()),
- invoicesAuditLogs.getInvoiceItemsAuditLogs()));
+ result.add(new InvoiceJson(invoice, accountAuditLogs));
}
return Response.status(Status.OK).entity(result).build();
} else {
final List<InvoiceJson> result = new LinkedList<InvoiceJson>();
for (final Invoice invoice : invoices) {
- result.add(new InvoiceJson(invoice,
- invoicesAuditLogs.getInvoiceAuditLogs().get(invoice.getId())));
+ result.add(new InvoiceJson(invoice, accountAuditLogs.getAuditLogsForInvoice(invoice.getId())));
}
return Response.status(Status.OK).entity(result).build();
@@ -681,11 +672,12 @@ public class AccountResource extends JaxRsResourceBase {
@GET
@Path("/{accountId:" + UUID_PATTERN + "}/" + TAGS)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id,
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String accountIdString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@QueryParam(QUERY_TAGS_INCLUDED_DELETED) @DefaultValue("false") final Boolean includedDeleted,
@javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id), auditMode, includedDeleted, context.createContext(request));
+ final UUID accountId = UUID.fromString(accountIdString);
+ return super.getTags(accountId, accountId, auditMode, includedDeleted, context.createContext(request));
}
@POST
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
index c0583f2..e7aa16d 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/BundleResource.java
@@ -57,6 +57,7 @@ import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.api.TagUserApi;
import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.TenantContext;
import com.google.inject.Inject;
@@ -90,10 +91,9 @@ public class BundleResource extends JaxRsResourceBase {
@Produces(APPLICATION_JSON)
public Response getBundle(@PathParam("bundleId") final String bundleId,
@javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException {
-
final UUID id = UUID.fromString(bundleId);
final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(id, context.createContext(request));
- final BundleJson json = new BundleJson(bundle, null, null, null);
+ final BundleJson json = new BundleJson(bundle, null);
return Response.status(Status.OK).entity(json).build();
}
@@ -102,7 +102,7 @@ public class BundleResource extends JaxRsResourceBase {
public Response getBundleByKey(@QueryParam(QUERY_EXTERNAL_KEY) final String externalKey,
@javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException {
final SubscriptionBundle bundle = subscriptionApi.getActiveSubscriptionBundleForExternalKey(externalKey, context.createContext(request));
- final BundleJson json = new BundleJson(bundle, null, null, null);
+ final BundleJson json = new BundleJson(bundle, null);
return Response.status(Status.OK).entity(json).build();
}
@@ -184,11 +184,14 @@ public class BundleResource extends JaxRsResourceBase {
@GET
@Path("/{bundleId:" + UUID_PATTERN + "}/" + TAGS)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id,
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String bundleIdString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@QueryParam(QUERY_TAGS_INCLUDED_DELETED) @DefaultValue("false") final Boolean includedDeleted,
- @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id), auditMode, includedDeleted, context.createContext(request));
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException, SubscriptionApiException {
+ final UUID bundleId = UUID.fromString(bundleIdString);
+ final TenantContext tenantContext = context.createContext(request);
+ final SubscriptionBundle bundle = subscriptionApi.getSubscriptionBundle(bundleId, context.createContext(request));
+ return super.getTags(bundle.getAccountId(), bundleId, auditMode, includedDeleted, tenantContext);
}
@PUT
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
index 2068d70..0af2810 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/InvoiceResource.java
@@ -67,13 +67,12 @@ import com.ning.billing.util.api.CustomFieldUserApi;
import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.api.TagUserApi;
-import com.ning.billing.util.audit.AuditLogsForInvoices;
-import com.ning.billing.util.audit.AuditLogsForPayments;
+import com.ning.billing.util.audit.AccountAuditLogs;
+import com.ning.billing.util.audit.AccountAuditLogsForObjectType;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.TenantContext;
import com.google.common.base.Objects;
-import com.google.common.collect.ImmutableList;
import com.google.inject.Inject;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
@@ -115,19 +114,12 @@ public class InvoiceResource extends JaxRsResourceBase {
@javax.ws.rs.core.Context final HttpServletRequest request) throws InvoiceApiException {
final TenantContext tenantContext = context.createContext(request);
final Invoice invoice = invoiceApi.getInvoice(UUID.fromString(invoiceId), tenantContext);
- final AuditLogsForInvoices invoicesAuditLogs = auditUserApi.getAuditLogsForInvoices(ImmutableList.<Invoice>of(invoice),
- auditMode.getLevel(),
- tenantContext);
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(invoice.getAccountId(), auditMode.getLevel(), tenantContext);
if (invoice == null) {
throw new InvoiceApiException(ErrorCode.INVOICE_NOT_FOUND, invoiceId);
} else {
- final InvoiceJson json = withItems ?
- new InvoiceJson(invoice,
- invoicesAuditLogs.getInvoiceAuditLogs().get(invoice.getId()),
- invoicesAuditLogs.getInvoiceItemsAuditLogs()) :
- new InvoiceJson(invoice,
- invoicesAuditLogs.getInvoiceAuditLogs().get(invoice.getId()));
+ final InvoiceJson json = new InvoiceJson(invoice, accountAuditLogs);
return Response.status(Status.OK).entity(json).build();
}
}
@@ -141,19 +133,12 @@ public class InvoiceResource extends JaxRsResourceBase {
@javax.ws.rs.core.Context final HttpServletRequest request) throws InvoiceApiException {
final TenantContext tenantContext = context.createContext(request);
final Invoice invoice = invoiceApi.getInvoiceByNumber(invoiceNumber, tenantContext);
- final AuditLogsForInvoices invoicesAuditLogs = auditUserApi.getAuditLogsForInvoices(ImmutableList.<Invoice>of(invoice),
- auditMode.getLevel(),
- tenantContext);
+ final AccountAuditLogs accountAuditLogs = auditUserApi.getAccountAuditLogs(invoice.getAccountId(), auditMode.getLevel(), tenantContext);
if (invoice == null) {
throw new InvoiceApiException(ErrorCode.INVOICE_NOT_FOUND, invoiceNumber);
} else {
- final InvoiceJson json = withItems ?
- new InvoiceJson(invoice,
- invoicesAuditLogs.getInvoiceAuditLogs().get(invoice.getId()),
- invoicesAuditLogs.getInvoiceItemsAuditLogs()) :
- new InvoiceJson(invoice,
- invoicesAuditLogs.getInvoiceAuditLogs().get(invoice.getId()));
+ final InvoiceJson json = new InvoiceJson(invoice, accountAuditLogs);
return Response.status(Status.OK).entity(json).build();
}
}
@@ -182,7 +167,7 @@ public class InvoiceResource extends JaxRsResourceBase {
final Invoice generatedInvoice = invoiceApi.triggerInvoiceGeneration(UUID.fromString(accountId), inputDate, dryRun,
callContext);
if (dryRun) {
- return Response.status(Status.OK).entity(new InvoiceJson(generatedInvoice, null)).build();
+ return Response.status(Status.OK).entity(new InvoiceJson(generatedInvoice)).build();
} else {
return uriBuilder.buildResponse(InvoiceResource.class, "getInvoice", generatedInvoice.getId());
}
@@ -330,11 +315,18 @@ public class InvoiceResource extends JaxRsResourceBase {
@javax.ws.rs.core.Context final HttpServletRequest request) throws PaymentApiException {
final TenantContext tenantContext = context.createContext(request);
final List<Payment> payments = paymentApi.getInvoicePayments(UUID.fromString(invoiceId), tenantContext);
- final AuditLogsForPayments auditLogsForPayments = auditUserApi.getAuditLogsForPayments(payments, auditMode.getLevel(), tenantContext);
-
final List<PaymentJson> result = new ArrayList<PaymentJson>(payments.size());
+ if (payments.size() == 0) {
+ return Response.status(Status.OK).entity(result).build();
+ }
+
+ final AccountAuditLogsForObjectType auditLogsForPayments = auditUserApi.getAccountAuditLogs(payments.get(0).getAccountId(),
+ ObjectType.PAYMENT,
+ auditMode.getLevel(),
+ tenantContext);
+
for (final Payment cur : payments) {
- result.add(new PaymentJson(cur, auditLogsForPayments.getPaymentsAuditLogs().get(cur.getId())));
+ result.add(new PaymentJson(cur, auditLogsForPayments.getAuditLogs(cur.getId())));
}
return Response.status(Status.OK).entity(result).build();
@@ -428,11 +420,14 @@ public class InvoiceResource extends JaxRsResourceBase {
@GET
@Path("/{invoiceId:" + UUID_PATTERN + "}/" + TAGS)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id,
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String invoiceIdString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@QueryParam(QUERY_TAGS_INCLUDED_DELETED) @DefaultValue("false") final Boolean includedDeleted,
- @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id), auditMode, includedDeleted, context.createContext(request));
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException, InvoiceApiException {
+ final UUID invoiceId = UUID.fromString(invoiceIdString);
+ final TenantContext tenantContext = context.createContext(request);
+ final Invoice invoice = invoiceApi.getInvoice(invoiceId, tenantContext);
+ return super.getTags(invoice.getAccountId(), invoiceId, auditMode, includedDeleted, tenantContext);
}
@POST
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
index 0e1d63c..e583cd4 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/JaxRsResourceBase.java
@@ -50,6 +50,7 @@ import com.ning.billing.util.api.CustomFieldUserApi;
import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.api.TagUserApi;
+import com.ning.billing.util.audit.AccountAuditLogsForObjectType;
import com.ning.billing.util.audit.AuditLog;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.TenantContext;
@@ -100,8 +101,9 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
return null;
}
- protected Response getTags(final UUID taggedObjectId, final AuditMode auditMode, final boolean includeDeleted, final TenantContext context) throws TagDefinitionApiException {
+ protected Response getTags(final UUID accountId, final UUID taggedObjectId, final AuditMode auditMode, final boolean includeDeleted, final TenantContext context) throws TagDefinitionApiException {
final List<Tag> tags = tagUserApi.getTagsForObject(taggedObjectId, getObjectType(), includeDeleted, context);
+ final AccountAuditLogsForObjectType tagsAuditLogs = auditUserApi.getAccountAuditLogs(accountId, ObjectType.TAG, auditMode.getLevel(), context);
final Map<UUID, TagDefinition> tagDefinitionsCache = new HashMap<UUID, TagDefinition>();
final Collection<TagJson> result = new LinkedList<TagJson>();
@@ -111,8 +113,7 @@ public abstract class JaxRsResourceBase implements JaxrsResource {
}
final TagDefinition tagDefinition = tagDefinitionsCache.get(tag.getTagDefinitionId());
- // TODO PIERRE - Bulk API
- final List<AuditLog> auditLogs = auditUserApi.getAuditLogs(tag.getId(), ObjectType.TAG, auditMode.getLevel(), context);
+ final List<AuditLog> auditLogs = tagsAuditLogs.getAuditLogs(tag.getId());
result.add(new TagJson(tagDefinition, auditLogs));
}
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
index 21a4ef1..8f99a77 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/PaymentResource.java
@@ -265,11 +265,14 @@ public class PaymentResource extends JaxRsResourceBase {
@GET
@Path("/{paymentId:" + UUID_PATTERN + "}/" + TAGS)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id,
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String paymentIdString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@QueryParam(QUERY_TAGS_INCLUDED_DELETED) @DefaultValue("false") final Boolean includedDeleted,
- @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id), auditMode, includedDeleted, context.createContext(request));
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException, PaymentApiException {
+ final UUID paymentId = UUID.fromString(paymentIdString);
+ final TenantContext tenantContext = context.createContext(request);
+ final Payment payment = paymentApi.getPayment(paymentId, false, tenantContext);
+ return super.getTags(payment.getAccountId(), paymentId, auditMode, includedDeleted, tenantContext);
}
@POST
diff --git a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
index 4e4a22f..eeb33e6 100644
--- a/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
+++ b/jaxrs/src/main/java/com/ning/billing/jaxrs/resources/SubscriptionResource.java
@@ -74,6 +74,7 @@ import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
import com.ning.billing.util.api.TagUserApi;
import com.ning.billing.util.callcontext.CallContext;
+import com.ning.billing.util.callcontext.TenantContext;
import com.ning.billing.util.userrequest.CompletionUserRequestBase;
import com.google.inject.Inject;
@@ -114,7 +115,7 @@ public class SubscriptionResource extends JaxRsResourceBase {
@javax.ws.rs.core.Context final HttpServletRequest request) throws SubscriptionApiException {
final UUID uuid = UUID.fromString(subscriptionId);
final Subscription subscription = subscriptionApi.getSubscriptionForEntitlementId(uuid, context.createContext(request));
- final SubscriptionJson json = new SubscriptionJson(subscription, null, null, null);
+ final SubscriptionJson json = new SubscriptionJson(subscription, null, null);
return Response.status(Status.OK).entity(json).build();
}
@@ -429,11 +430,14 @@ public class SubscriptionResource extends JaxRsResourceBase {
@GET
@Path("/{subscriptionId:" + UUID_PATTERN + "}/" + TAGS)
@Produces(APPLICATION_JSON)
- public Response getTags(@PathParam(ID_PARAM_NAME) final String id,
+ public Response getTags(@PathParam(ID_PARAM_NAME) final String subscriptionIdString,
@QueryParam(QUERY_AUDIT) @DefaultValue("NONE") final AuditMode auditMode,
@QueryParam(QUERY_TAGS_INCLUDED_DELETED) @DefaultValue("false") final Boolean includedDeleted,
- @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException {
- return super.getTags(UUID.fromString(id), auditMode, includedDeleted, context.createContext(request));
+ @javax.ws.rs.core.Context final HttpServletRequest request) throws TagDefinitionApiException, SubscriptionApiException {
+ final UUID subscriptionId = UUID.fromString(subscriptionIdString);
+ final TenantContext tenantContext = context.createContext(request);
+ final Subscription subscription = subscriptionApi.getSubscriptionForEntitlementId(subscriptionId, tenantContext);
+ return super.getTags(subscription.getAccountId(), subscriptionId, auditMode, includedDeleted, tenantContext);
}
@POST
diff --git a/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAuditLogJson.java b/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAuditLogJson.java
index 30a7eea..d123f56 100644
--- a/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAuditLogJson.java
+++ b/jaxrs/src/test/java/com/ning/billing/jaxrs/json/TestAuditLogJson.java
@@ -22,10 +22,12 @@ import org.joda.time.DateTime;
import org.testng.Assert;
import org.testng.annotations.Test;
+import com.ning.billing.ObjectType;
import com.ning.billing.jaxrs.JaxrsTestSuiteNoDB;
import com.ning.billing.util.audit.AuditLog;
import com.ning.billing.util.audit.ChangeType;
import com.ning.billing.util.audit.DefaultAuditLog;
+import com.ning.billing.util.audit.dao.AuditLogModelDao;
import com.ning.billing.util.dao.EntityAudit;
import com.ning.billing.util.dao.TableName;
@@ -67,7 +69,7 @@ public class TestAuditLogJson extends JaxrsTestSuiteNoDB {
final ChangeType changeType = ChangeType.DELETE;
final EntityAudit entityAudit = new EntityAudit(tableName, recordId, changeType, null);
- final AuditLog auditLog = new DefaultAuditLog(entityAudit, callContext);
+ final AuditLog auditLog = new DefaultAuditLog(new AuditLogModelDao(entityAudit, callContext), ObjectType.ACCOUNT_EMAIL, UUID.randomUUID());
final AuditLogJson auditLogJson = new AuditLogJson(auditLog);
Assert.assertEquals(auditLogJson.getChangeType(), changeType.toString());
diff --git a/server/src/main/java/com/ning/billing/server/modules/DBIProvider.java b/server/src/main/java/com/ning/billing/server/modules/DBIProvider.java
index 81d747f..7891ebb 100644
--- a/server/src/main/java/com/ning/billing/server/modules/DBIProvider.java
+++ b/server/src/main/java/com/ning/billing/server/modules/DBIProvider.java
@@ -27,6 +27,7 @@ import org.skife.jdbi.v2.tweak.TransactionHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.ning.billing.util.dao.AuditLogModelDaoMapper;
import com.ning.billing.util.dao.DateTimeArgumentFactory;
import com.ning.billing.util.dao.DateTimeZoneArgumentFactory;
import com.ning.billing.util.dao.EnumArgumentFactory;
@@ -71,6 +72,7 @@ public class DBIProvider implements Provider<DBI> {
dbi.registerArgumentFactory(new LocalDateArgumentFactory());
dbi.registerArgumentFactory(new EnumArgumentFactory());
dbi.registerMapper(new UuidMapper());
+ dbi.registerMapper(new AuditLogModelDaoMapper());
if (sqlLog != null) {
dbi.setSQLLog(sqlLog);
diff --git a/util/src/main/java/com/ning/billing/util/audit/api/DefaultAuditUserApi.java b/util/src/main/java/com/ning/billing/util/audit/api/DefaultAuditUserApi.java
index 6f629b8..fd57844 100644
--- a/util/src/main/java/com/ning/billing/util/audit/api/DefaultAuditUserApi.java
+++ b/util/src/main/java/com/ning/billing/util/audit/api/DefaultAuditUserApi.java
@@ -16,44 +16,24 @@
package com.ning.billing.util.audit.api;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.UUID;
-import javax.annotation.Nullable;
import javax.inject.Inject;
import com.ning.billing.ObjectType;
-import com.ning.billing.entitlement.api.Subscription;
-import com.ning.billing.entitlement.api.SubscriptionBundle;
-import com.ning.billing.entitlement.api.SubscriptionEvent;
-import com.ning.billing.invoice.api.Invoice;
-import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.invoice.api.InvoicePayment;
-import com.ning.billing.payment.api.Payment;
-import com.ning.billing.payment.api.Refund;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.api.AuditUserApi;
+import com.ning.billing.util.audit.AccountAuditLogs;
+import com.ning.billing.util.audit.AccountAuditLogsForObjectType;
import com.ning.billing.util.audit.AuditLog;
-import com.ning.billing.util.audit.AuditLogsForAccount;
-import com.ning.billing.util.audit.AuditLogsForBundles;
-import com.ning.billing.util.audit.AuditLogsForInvoicePayments;
-import com.ning.billing.util.audit.AuditLogsForInvoices;
-import com.ning.billing.util.audit.AuditLogsForPayments;
-import com.ning.billing.util.audit.AuditLogsForRefunds;
-import com.ning.billing.util.audit.DefaultAuditLogsForBundles;
-import com.ning.billing.util.audit.DefaultAuditLogsForInvoicePayments;
-import com.ning.billing.util.audit.DefaultAuditLogsForInvoices;
-import com.ning.billing.util.audit.DefaultAuditLogsForPayments;
-import com.ning.billing.util.audit.DefaultAuditLogsForRefunds;
+import com.ning.billing.util.audit.DefaultAccountAuditLogs;
+import com.ning.billing.util.audit.DefaultAccountAuditLogsForObjectType;
import com.ning.billing.util.audit.dao.AuditDao;
import com.ning.billing.util.callcontext.InternalCallContextFactory;
import com.ning.billing.util.callcontext.TenantContext;
import com.ning.billing.util.dao.TableName;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
public class DefaultAuditUserApi implements AuditUserApi {
@@ -68,77 +48,28 @@ public class DefaultAuditUserApi implements AuditUserApi {
}
@Override
- public AuditLogsForAccount getAuditLogsForAccount(final UUID accountId, final AuditLevel auditLevel, final TenantContext context) {
- return new DefaultAuditLogsForAccount(getAuditLogs(accountId, ObjectType.ACCOUNT, auditLevel, context));
- }
-
- @Override
- public AuditLogsForBundles getAuditLogsForBundles(final List<SubscriptionBundle> bundles, final AuditLevel auditLevel, final TenantContext context) {
- final Map<UUID, List<AuditLog>> bundlesAuditLogs = new HashMap<UUID, List<AuditLog>>();
- final Map<UUID, List<AuditLog>> subscriptionsAuditLogs = new HashMap<UUID, List<AuditLog>>();
- final Map<UUID, List<AuditLog>> subscriptionEventsAuditLogs = new HashMap<UUID, List<AuditLog>>();
- for (final SubscriptionBundle bundle : bundles) {
- bundlesAuditLogs.put(bundle.getId(), getAuditLogs(bundle.getId(), ObjectType.BUNDLE, auditLevel, context));
- for (final Subscription cur : bundle.getSubscriptions()) {
-
- final ImmutableList<SubscriptionEvent> events = ImmutableList.<SubscriptionEvent>copyOf(Collections2.filter(bundle.getTimeline().getSubscriptionEvents(), new Predicate<SubscriptionEvent>() {
- @Override
- public boolean apply(@Nullable final SubscriptionEvent input) {
- return input.getEntitlementId().equals(cur.getId());
- }
- }));
- subscriptionsAuditLogs.put(cur.getId(), getAuditLogs(cur.getId(), ObjectType.SUBSCRIPTION, auditLevel, context));
- for (final SubscriptionEvent event : events) {
- subscriptionEventsAuditLogs.put(event.getId(), getAuditLogs(event.getId(), event.getSubscriptionEventType().getObjectType(), auditLevel, context));
- }
- }
- }
-
- return new DefaultAuditLogsForBundles(bundlesAuditLogs, subscriptionsAuditLogs, subscriptionEventsAuditLogs);
- }
-
- @Override
- public AuditLogsForInvoicePayments getAuditLogsForInvoicePayments(final List<InvoicePayment> invoicePayments, final AuditLevel auditLevel, final TenantContext context) {
- final Map<UUID, List<AuditLog>> invoicePaymentsAuditLogs = new HashMap<UUID, List<AuditLog>>();
- for (final InvoicePayment invoicePayment : invoicePayments) {
- invoicePaymentsAuditLogs.put(invoicePayment.getId(), getAuditLogs(invoicePayment.getId(), ObjectType.INVOICE_PAYMENT, auditLevel, context));
- }
-
- return new DefaultAuditLogsForInvoicePayments(invoicePaymentsAuditLogs);
- }
-
- @Override
- public AuditLogsForRefunds getAuditLogsForRefunds(final List<Refund> refunds, final AuditLevel auditLevel, final TenantContext context) {
- final Map<UUID, List<AuditLog>> refundsAuditLogs = new HashMap<UUID, List<AuditLog>>();
- for (final Refund refund : refunds) {
- refundsAuditLogs.put(refund.getId(), getAuditLogs(refund.getId(), ObjectType.REFUND, auditLevel, context));
+ public AccountAuditLogs getAccountAuditLogs(final UUID accountId, final AuditLevel auditLevel, final TenantContext tenantContext) {
+ // Optimization - bail early
+ if (AuditLevel.NONE.equals(auditLevel)) {
+ return new DefaultAccountAuditLogs(accountId);
}
- return new DefaultAuditLogsForRefunds(refundsAuditLogs);
+ return auditDao.getAuditLogsForAccountRecordId(auditLevel, internalCallContextFactory.createInternalTenantContext(accountId, tenantContext));
}
@Override
- public AuditLogsForPayments getAuditLogsForPayments(final List<Payment> payments, final AuditLevel auditLevel, final TenantContext context) {
- final Map<UUID, List<AuditLog>> paymentsAuditLogs = new HashMap<UUID, List<AuditLog>>();
- for (final Payment payment : payments) {
- paymentsAuditLogs.put(payment.getId(), getAuditLogs(payment.getId(), ObjectType.PAYMENT, auditLevel, context));
+ public AccountAuditLogsForObjectType getAccountAuditLogs(final UUID accountId, final ObjectType objectType, final AuditLevel auditLevel, final TenantContext tenantContext) {
+ // Optimization - bail early
+ if (AuditLevel.NONE.equals(auditLevel)) {
+ return new DefaultAccountAuditLogsForObjectType(auditLevel);
}
- return new DefaultAuditLogsForPayments(paymentsAuditLogs);
- }
-
- @Override
- public AuditLogsForInvoices getAuditLogsForInvoices(final List<Invoice> invoices, final AuditLevel auditLevel, final TenantContext context) {
- final Map<UUID, List<AuditLog>> invoiceAuditLogs = new HashMap<UUID, List<AuditLog>>();
- final Map<UUID, List<AuditLog>> invoiceItemsAuditLogs = new HashMap<UUID, List<AuditLog>>();
- for (final Invoice invoice : invoices) {
- invoiceAuditLogs.put(invoice.getId(), getAuditLogs(invoice.getId(), ObjectType.INVOICE, auditLevel, context));
- for (final InvoiceItem invoiceItem : invoice.getInvoiceItems()) {
- invoiceItemsAuditLogs.put(invoiceItem.getId(), getAuditLogs(invoiceItem.getId(), ObjectType.INVOICE_ITEM, auditLevel, context));
- }
+ final TableName tableName = getTableNameFromObjectType(objectType);
+ if (tableName == null) {
+ return new DefaultAccountAuditLogsForObjectType(auditLevel);
}
- return new DefaultAuditLogsForInvoices(invoiceAuditLogs, invoiceItemsAuditLogs);
+ return auditDao.getAuditLogsForAccountRecordId(tableName, auditLevel, internalCallContextFactory.createInternalTenantContext(accountId, tenantContext));
}
@Override
diff --git a/util/src/main/java/com/ning/billing/util/audit/dao/AuditDao.java b/util/src/main/java/com/ning/billing/util/audit/dao/AuditDao.java
index ab88cbd..294eda3 100644
--- a/util/src/main/java/com/ning/billing/util/audit/dao/AuditDao.java
+++ b/util/src/main/java/com/ning/billing/util/audit/dao/AuditDao.java
@@ -19,12 +19,20 @@ package com.ning.billing.util.audit.dao;
import java.util.List;
import java.util.UUID;
+import com.ning.billing.callcontext.InternalTenantContext;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.audit.AuditLog;
-import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.util.audit.DefaultAccountAuditLogs;
+import com.ning.billing.util.audit.DefaultAccountAuditLogsForObjectType;
import com.ning.billing.util.dao.TableName;
public interface AuditDao {
+ // Make sure to consume all or call close() when done for release the connection
+ public DefaultAccountAuditLogs getAuditLogsForAccountRecordId(AuditLevel auditLevel, InternalTenantContext context);
+
+ // Make sure to consume all or call close() when done for release the connection
+ public DefaultAccountAuditLogsForObjectType getAuditLogsForAccountRecordId(TableName tableName, AuditLevel auditLevel, InternalTenantContext context);
+
public List<AuditLog> getAuditLogsForId(TableName tableName, UUID objectId, AuditLevel auditLevel, InternalTenantContext context);
}
diff --git a/util/src/main/java/com/ning/billing/util/audit/dao/DefaultAuditDao.java b/util/src/main/java/com/ning/billing/util/audit/dao/DefaultAuditDao.java
index 1aa55e6..b49a8b7 100644
--- a/util/src/main/java/com/ning/billing/util/audit/dao/DefaultAuditDao.java
+++ b/util/src/main/java/com/ning/billing/util/audit/dao/DefaultAuditDao.java
@@ -16,6 +16,7 @@
package com.ning.billing.util.audit.dao;
+import java.util.Iterator;
import java.util.List;
import java.util.UUID;
@@ -23,12 +24,16 @@ import javax.inject.Inject;
import org.skife.jdbi.v2.IDBI;
+import com.ning.billing.ObjectType;
+import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.clock.Clock;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.audit.AuditLog;
import com.ning.billing.util.audit.ChangeType;
+import com.ning.billing.util.audit.DefaultAccountAuditLogs;
+import com.ning.billing.util.audit.DefaultAccountAuditLogsForObjectType;
+import com.ning.billing.util.audit.DefaultAuditLog;
import com.ning.billing.util.cache.CacheControllerDispatcher;
-import com.ning.billing.callcontext.InternalTenantContext;
-import com.ning.billing.clock.Clock;
import com.ning.billing.util.dao.NonEntityDao;
import com.ning.billing.util.dao.NonEntitySqlDao;
import com.ning.billing.util.dao.TableName;
@@ -37,7 +42,10 @@ import com.ning.billing.util.entity.dao.EntitySqlDaoTransactionWrapper;
import com.ning.billing.util.entity.dao.EntitySqlDaoTransactionalJdbiWrapper;
import com.ning.billing.util.entity.dao.EntitySqlDaoWrapperFactory;
+import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
public class DefaultAuditDao implements AuditDao {
@@ -51,6 +59,76 @@ public class DefaultAuditDao implements AuditDao {
}
@Override
+ public DefaultAccountAuditLogs getAuditLogsForAccountRecordId(final AuditLevel auditLevel, final InternalTenantContext context) {
+ final UUID accountId = nonEntitySqlDao.getIdFromObject(context.getAccountRecordId(), TableName.ACCOUNT.getTableName());
+
+ // Lazy evaluate records to minimize the memory footprint (these can yield a lot of results)
+ // We usually always want to wrap our queries in an EntitySqlDaoTransactionWrapper... except here.
+ // Since we want to stream the results out, we don't want to auto-commit when this method returns.
+ final EntitySqlDao auditSqlDao = transactionalSqlDao.onDemand(EntitySqlDao.class);
+ final Iterator<AuditLogModelDao> auditLogsForAccountRecordId = auditSqlDao.getAuditLogsForAccountRecordId(context);
+ final Iterator<AuditLog> allAuditLogs = buildAuditLogsFromModelDao(auditLogsForAccountRecordId);
+
+ return new DefaultAccountAuditLogs(accountId, auditLevel, allAuditLogs);
+ }
+
+ @Override
+ public DefaultAccountAuditLogsForObjectType getAuditLogsForAccountRecordId(final TableName tableName, final AuditLevel auditLevel, final InternalTenantContext context) {
+ final String actualTableName;
+ if (tableName.hasHistoryTable()) {
+ actualTableName = tableName.getHistoryTableName().name(); // upper cased
+ } else {
+ actualTableName = tableName.getTableName();
+ }
+
+ // Lazy evaluate records to minimize the memory footprint (these can yield a lot of results)
+ // We usually always want to wrap our queries in an EntitySqlDaoTransactionWrapper... except here.
+ // Since we want to stream the results out, we don't want to auto-commit when this method returns.
+ final EntitySqlDao auditSqlDao = transactionalSqlDao.onDemand(EntitySqlDao.class);
+ final Iterator<AuditLogModelDao> auditLogsForTableNameAndAccountRecordId = auditSqlDao.getAuditLogsForTableNameAndAccountRecordId(actualTableName, context);
+ final Iterator<AuditLog> allAuditLogs = buildAuditLogsFromModelDao(auditLogsForTableNameAndAccountRecordId);
+
+ return new DefaultAccountAuditLogsForObjectType(auditLevel, allAuditLogs);
+ }
+
+ private Iterator<AuditLog> buildAuditLogsFromModelDao(final Iterator<AuditLogModelDao> auditLogsForAccountRecordId) {
+ return Iterators.<AuditLogModelDao, AuditLog>transform(auditLogsForAccountRecordId,
+ new Function<AuditLogModelDao, AuditLog>() {
+ @Override
+ public AuditLog apply(final AuditLogModelDao input) {
+ // If input is for e.g. TAG_DEFINITION_HISTORY, retrieve TAG_DEFINITIONS
+ // For tables without history, e.g. TENANT, originalTableNameForHistoryTableName will be null
+ final TableName originalTableNameForHistoryTableName = findTableNameForHistoryTableName(input.getTableName());
+
+ final ObjectType objectType;
+ final UUID auditedEntityId;
+ if (originalTableNameForHistoryTableName != null) {
+ // input point to a history entry
+ objectType = originalTableNameForHistoryTableName.getObjectType();
+ auditedEntityId = nonEntitySqlDao.getIdFromHistoryRecordId(input.getTargetRecordId(),
+ originalTableNameForHistoryTableName.getTableName(),
+ input.getTableName().getTableName());
+ } else {
+ objectType = input.getTableName().getObjectType();
+ auditedEntityId = nonEntitySqlDao.getIdFromObject(input.getTargetRecordId(), input.getTableName().getTableName());
+ }
+
+ return new DefaultAuditLog(input, objectType, auditedEntityId);
+ }
+
+ private TableName findTableNameForHistoryTableName(final TableName historyTableName) {
+ for (final TableName tableName : TableName.values()) {
+ if (historyTableName.equals(tableName.getHistoryTableName())) {
+ return tableName;
+ }
+ }
+
+ return null;
+ }
+ });
+ }
+
+ @Override
public List<AuditLog> getAuditLogsForId(final TableName tableName, final UUID objectId, final AuditLevel auditLevel, final InternalTenantContext context) {
if (tableName.hasHistoryTable()) {
return doGetAuditLogsViaHistoryForId(tableName, objectId, auditLevel, context);
@@ -64,7 +142,7 @@ public class DefaultAuditDao implements AuditDao {
if (recordId == null) {
return ImmutableList.<AuditLog>of();
} else {
- return getAuditLogsForRecordId(tableName, recordId, auditLevel, context);
+ return getAuditLogsForRecordId(tableName, objectId, recordId, auditLevel, context);
}
}
@@ -78,32 +156,44 @@ public class DefaultAuditDao implements AuditDao {
final List<AuditLog> allAuditLogs = transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<AuditLog>>() {
@Override
public List<AuditLog> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
- return entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsViaHistoryForTargetRecordId(historyTableName.name(),
- historyTableName.getTableName().toLowerCase(),
- targetRecordId,
- context);
+ final List<AuditLogModelDao> auditLogsViaHistoryForTargetRecordId = entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsViaHistoryForTargetRecordId(historyTableName.name(),
+ historyTableName.getTableName().toLowerCase(),
+ targetRecordId,
+ context);
+ return buildAuditLogsFromModelDao(auditLogsViaHistoryForTargetRecordId, tableName.getObjectType(), objectId);
}
});
- return buildAuditLogs(auditLevel, allAuditLogs);
+ return filterAuditLogs(auditLevel, allAuditLogs);
}
- private List<AuditLog> getAuditLogsForRecordId(final TableName tableName, final Long targetRecordId, final AuditLevel auditLevel, final InternalTenantContext context) {
+ private List<AuditLog> getAuditLogsForRecordId(final TableName tableName, final UUID auditedEntityId, final Long targetRecordId, final AuditLevel auditLevel, final InternalTenantContext context) {
final List<AuditLog> allAuditLogs = transactionalSqlDao.execute(new EntitySqlDaoTransactionWrapper<List<AuditLog>>() {
@Override
public List<AuditLog> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDao> entitySqlDaoWrapperFactory) throws Exception {
- return entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsForTargetRecordId(tableName.name(),
- targetRecordId,
- context);
+ final List<AuditLogModelDao> auditLogsForTargetRecordId = entitySqlDaoWrapperFactory.become(EntitySqlDao.class).getAuditLogsForTargetRecordId(tableName.name(),
+ targetRecordId,
+ context);
+ return buildAuditLogsFromModelDao(auditLogsForTargetRecordId, tableName.getObjectType(), auditedEntityId);
}
});
- return buildAuditLogs(auditLevel, allAuditLogs);
+ return filterAuditLogs(auditLevel, allAuditLogs);
+ }
+
+ private List<AuditLog> buildAuditLogsFromModelDao(final List<AuditLogModelDao> auditLogsForAccountRecordId, final ObjectType objectType, final UUID auditedEntityId) {
+ return Lists.<AuditLogModelDao, AuditLog>transform(auditLogsForAccountRecordId,
+ new Function<AuditLogModelDao, AuditLog>() {
+ @Override
+ public AuditLog apply(final AuditLogModelDao input) {
+ return new DefaultAuditLog(input, objectType, auditedEntityId);
+ }
+ });
}
- private List<AuditLog> buildAuditLogs(final AuditLevel auditLevel, final List<AuditLog> auditLogs) {
+ private List<AuditLog> filterAuditLogs(final AuditLevel auditLevel, final List<AuditLog> auditLogs) {
// TODO Do the filtering in the query
if (AuditLevel.FULL.equals(auditLevel)) {
return auditLogs;
- } else if (AuditLevel.MINIMAL.equals(auditLevel) && auditLogs.size() > 0) {
+ } else if (AuditLevel.MINIMAL.equals(auditLevel) && !auditLogs.isEmpty()) {
if (ChangeType.INSERT.equals(auditLogs.get(0).getChangeType())) {
return ImmutableList.<AuditLog>of(auditLogs.get(0));
} else {
diff --git a/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogs.java b/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogs.java
new file mode 100644
index 0000000..ef1f691
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogs.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.audit;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import com.ning.billing.ObjectType;
+import com.ning.billing.util.api.AuditLevel;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.AbstractIterator;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterators;
+
+public class DefaultAccountAuditLogs implements AccountAuditLogs {
+
+ private final UUID accountId;
+ private final AuditLevel auditLevel;
+ private final Collection<AuditLog> accountAuditLogs;
+
+ private final Map<ObjectType, DefaultAccountAuditLogsForObjectType> auditLogsCache = new HashMap<ObjectType, DefaultAccountAuditLogsForObjectType>();
+
+ public DefaultAccountAuditLogs(final UUID accountId) {
+ this(accountId, AuditLevel.NONE, Iterators.<AuditLog>emptyIterator());
+ }
+
+ public DefaultAccountAuditLogs(final UUID accountId, final AuditLevel auditLevel, final Iterator<AuditLog> accountAuditLogsOrderedByTableName) {
+ this.accountId = accountId;
+ this.auditLevel = auditLevel;
+ // TODO pierre - lame, we should be smarter to avoid loading all entries in memory. It's a bit tricky though...
+ this.accountAuditLogs = ImmutableList.<AuditLog>copyOf(accountAuditLogsOrderedByTableName);
+ }
+
+ public void close() {
+ // Make sure to go through the results to close the connection
+ // no-op for now, see TODO above
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForAccount() {
+ return getAuditLogs(ObjectType.BUNDLE).getAuditLogs(accountId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForBundle(final UUID bundleId) {
+ return getAuditLogs(ObjectType.BUNDLE).getAuditLogs(bundleId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForSubscription(final UUID subscriptionId) {
+ return getAuditLogs(ObjectType.SUBSCRIPTION).getAuditLogs(subscriptionId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForSubscriptionEvent(final UUID subscriptionEventId) {
+ return getAuditLogs(ObjectType.SUBSCRIPTION_EVENT).getAuditLogs(subscriptionEventId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForInvoice(final UUID invoiceId) {
+ return getAuditLogs(ObjectType.INVOICE).getAuditLogs(invoiceId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForInvoiceItem(final UUID invoiceItemId) {
+ return getAuditLogs(ObjectType.INVOICE_ITEM).getAuditLogs(invoiceItemId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForPayment(final UUID paymentId) {
+ return getAuditLogs(ObjectType.PAYMENT).getAuditLogs(paymentId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForRefund(final UUID refundId) {
+ return getAuditLogs(ObjectType.REFUND).getAuditLogs(refundId);
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogsForChargeback(final UUID chargebackId) {
+ return getAuditLogs(ObjectType.INVOICE_PAYMENT).getAuditLogs(chargebackId);
+ }
+
+ @Override
+ public AccountAuditLogsForObjectType getAuditLogs(final ObjectType objectType) {
+ if (auditLogsCache.get(objectType) == null) {
+ auditLogsCache.put(objectType, new DefaultAccountAuditLogsForObjectType(auditLevel, new ObjectTypeFilter(objectType, accountAuditLogs.iterator())));
+ }
+
+ // Should never be null
+ return auditLogsCache.get(objectType);
+ }
+
+ private final class ObjectTypeFilter extends AbstractIterator<AuditLog> {
+
+ private boolean hasSeenObjectType = false;
+
+ private final ObjectType objectType;
+ private final Iterator<AuditLog> accountAuditLogs;
+
+ private ObjectTypeFilter(final ObjectType objectType, final Iterator<AuditLog> accountAuditLogs) {
+ this.objectType = objectType;
+ this.accountAuditLogs = accountAuditLogs;
+ }
+
+ @Override
+ protected AuditLog computeNext() {
+ while (accountAuditLogs.hasNext()) {
+ final AuditLog element = accountAuditLogs.next();
+ if (predicate.apply(element)) {
+ hasSeenObjectType = true;
+ return element;
+ } else if (hasSeenObjectType) {
+ // Optimization trick: audit log records are ordered first by table name
+ // (hence object type) - when we are done and we switch to another ObjectType,
+ // we are guaranteed there is nothing left to do
+ return endOfData();
+ }
+ }
+
+ return endOfData();
+ }
+
+ private final Predicate<AuditLog> predicate = new Predicate<AuditLog>() {
+ @Override
+ public boolean apply(final AuditLog auditLog) {
+ return objectType.equals(auditLog.getAuditedObjectType());
+ }
+ };
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogsForObjectType.java b/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogsForObjectType.java
new file mode 100644
index 0000000..108b170
--- /dev/null
+++ b/util/src/main/java/com/ning/billing/util/audit/DefaultAccountAuditLogsForObjectType.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.util.audit;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+import com.ning.billing.util.api.AuditLevel;
+import com.ning.billing.util.customfield.ShouldntHappenException;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterators;
+
+public class DefaultAccountAuditLogsForObjectType implements AccountAuditLogsForObjectType {
+
+ private final Map<UUID, List<AuditLog>> auditLogsCache;
+
+ private final AuditLevel auditLevel;
+ private final Iterator<AuditLog> allAuditLogsForObjectType;
+
+ public DefaultAccountAuditLogsForObjectType(final AuditLevel auditLevel) {
+ this(auditLevel, Iterators.<AuditLog>emptyIterator());
+ }
+
+ public DefaultAccountAuditLogsForObjectType(final AuditLevel auditLevel, final Iterator<AuditLog> allAuditLogsForObjectType) {
+ this.auditLevel = auditLevel;
+ this.auditLogsCache = new HashMap<UUID, List<AuditLog>>();
+ this.allAuditLogsForObjectType = allAuditLogsForObjectType;
+ }
+
+ // Used by DefaultAccountAuditLogs
+ void initializeIfNeeded(final UUID objectId) {
+ if (auditLogsCache.get(objectId) == null) {
+ auditLogsCache.put(objectId, new LinkedList<AuditLog>());
+ }
+ }
+
+ public void close() {
+ // Make sure to go through the results to close the connection
+ while (allAuditLogsForObjectType.hasNext()) {
+ allAuditLogsForObjectType.next();
+ }
+ }
+
+ @Override
+ public List<AuditLog> getAuditLogs(final UUID objectId) {
+ switch (auditLevel) {
+ case FULL:
+ // We need to go through the whole list
+ cacheAllAuditLogs();
+
+ // We went through the whole list, mark we don't have any entry for it if needed
+ initializeIfNeeded(objectId);
+
+ // Should never be null
+ return auditLogsCache.get(objectId);
+ case MINIMAL:
+ if (auditLogsCache.get(objectId) == null) {
+ // We just want the first INSERT audit log
+ final AuditLog candidate = Iterators.<AuditLog>tryFind(allAuditLogsForObjectType,
+ new Predicate<AuditLog>() {
+ @Override
+ public boolean apply(final AuditLog auditLog) {
+ // As we consume the data source, cache the entries
+ cacheAuditLog(auditLog);
+
+ return objectId.equals(auditLog.getAuditedEntityId()) &&
+ // Given our ordering, this should always be true for the first entry
+ ChangeType.INSERT.equals(auditLog.getChangeType());
+ }
+ }).orNull();
+
+ if (candidate == null) {
+ // We went through the whole list, mark we don't have any entry for it
+ initializeIfNeeded(objectId);
+ }
+ }
+
+ // Should never be null
+ return auditLogsCache.get(objectId);
+ case NONE:
+ // Close the connection ASAP since we won't need it
+ close();
+ return ImmutableList.<AuditLog>of();
+ default:
+ throw new ShouldntHappenException("AuditLevel " + auditLevel + " unsupported");
+ }
+ }
+
+ private void cacheAllAuditLogs() {
+ while (allAuditLogsForObjectType.hasNext()) {
+ final AuditLog auditLog = allAuditLogsForObjectType.next();
+ cacheAuditLog(auditLog);
+ }
+ }
+
+ private void cacheAuditLog(final AuditLog auditLog) {
+ initializeIfNeeded(auditLog.getAuditedEntityId());
+ auditLogsCache.get(auditLog.getAuditedEntityId()).add(auditLog);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuilder sb = new StringBuilder("DefaultAccountAuditLogsForObjectType{");
+ sb.append("auditLogsCache=").append(auditLogsCache);
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ final DefaultAccountAuditLogsForObjectType that = (DefaultAccountAuditLogsForObjectType) o;
+
+ if (!auditLogsCache.equals(that.auditLogsCache)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return auditLogsCache.hashCode();
+ }
+}
diff --git a/util/src/main/java/com/ning/billing/util/audit/DefaultAuditLog.java b/util/src/main/java/com/ning/billing/util/audit/DefaultAuditLog.java
index 0c3e07e..b2deef3 100644
--- a/util/src/main/java/com/ning/billing/util/audit/DefaultAuditLog.java
+++ b/util/src/main/java/com/ning/billing/util/audit/DefaultAuditLog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2012 Ning, Inc.
+ * Copyright 2010-2013 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
@@ -16,56 +16,76 @@
package com.ning.billing.util.audit;
+import java.util.UUID;
+
import org.joda.time.DateTime;
-import com.ning.billing.util.callcontext.CallContext;
-import com.ning.billing.util.dao.EntityAudit;
+import com.ning.billing.ObjectType;
+import com.ning.billing.entity.EntityBase;
+import com.ning.billing.util.audit.dao.AuditLogModelDao;
+
+public class DefaultAuditLog extends EntityBase implements AuditLog {
-public class DefaultAuditLog extends EntityAudit implements AuditLog {
+ private final AuditLogModelDao auditLogModelDao;
+ private final ObjectType objectType;
+ private final UUID auditedEntityId;
- private final CallContext callContext;
+ public DefaultAuditLog(final AuditLogModelDao auditLogModelDao, final ObjectType objectType, final UUID auditedEntityId) {
+ super(auditLogModelDao);
+ this.auditLogModelDao = auditLogModelDao;
+ this.objectType = objectType;
+ this.auditedEntityId = auditedEntityId;
+ }
- public DefaultAuditLog(final EntityAudit entityAudit, final CallContext callContext) {
- super(entityAudit.getId(), entityAudit.getTableName(), entityAudit.getTargetRecordId(), entityAudit.getChangeType(), entityAudit.getCreatedDate());
- this.callContext = callContext;
+ @Override
+ public UUID getAuditedEntityId() {
+ return auditedEntityId;
}
+ @Override
+ public ObjectType getAuditedObjectType() {
+ return objectType;
+ }
+
+ @Override
+ public ChangeType getChangeType() {
+ return auditLogModelDao.getChangeType();
+ }
@Override
public String getUserName() {
- return callContext.getUserName();
+ return auditLogModelDao.getCallContext().getUserName();
}
@Override
public DateTime getCreatedDate() {
- return callContext.getCreatedDate();
+ return auditLogModelDao.getCallContext().getCreatedDate();
}
@Override
public String getReasonCode() {
- return callContext.getReasonCode();
+ return auditLogModelDao.getCallContext().getReasonCode();
}
@Override
public String getUserToken() {
- if (callContext.getUserToken() == null) {
+ if (auditLogModelDao.getCallContext().getUserToken() == null) {
return null;
} else {
- return callContext.getUserToken().toString();
+ return auditLogModelDao.getCallContext().getUserToken().toString();
}
}
@Override
public String getComment() {
- return callContext.getComments();
+ return auditLogModelDao.getCallContext().getComments();
}
@Override
public String toString() {
- final StringBuilder sb = new StringBuilder();
- sb.append("DefaultAuditLog {");
- sb.append(super.toString());
- sb.append(", callcontext=").append(callContext);
+ final StringBuilder sb = new StringBuilder("DefaultAuditLog{");
+ sb.append("auditLogModelDao=").append(auditLogModelDao);
+ sb.append(", auditedEntityId=").append(auditedEntityId);
sb.append('}');
return sb.toString();
}
@@ -84,7 +104,10 @@ public class DefaultAuditLog extends EntityAudit implements AuditLog {
final DefaultAuditLog that = (DefaultAuditLog) o;
- if (callContext != null ? !callContext.equals(that.callContext) : that.callContext != null) {
+ if (auditLogModelDao != null ? !auditLogModelDao.equals(that.auditLogModelDao) : that.auditLogModelDao != null) {
+ return false;
+ }
+ if (auditedEntityId != null ? !auditedEntityId.equals(that.auditedEntityId) : that.auditedEntityId != null) {
return false;
}
@@ -94,7 +117,8 @@ public class DefaultAuditLog extends EntityAudit implements AuditLog {
@Override
public int hashCode() {
int result = super.hashCode();
- result = 31 * result + (callContext != null ? callContext.hashCode() : 0);
+ result = 31 * result + (auditLogModelDao != null ? auditLogModelDao.hashCode() : 0);
+ result = 31 * result + (auditedEntityId != null ? auditedEntityId.hashCode() : 0);
return result;
}
}
diff --git a/util/src/main/java/com/ning/billing/util/dao/AuditSqlDao.java b/util/src/main/java/com/ning/billing/util/dao/AuditSqlDao.java
index d9f9b83..7f91aac 100644
--- a/util/src/main/java/com/ning/billing/util/dao/AuditSqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/dao/AuditSqlDao.java
@@ -16,6 +16,7 @@
package com.ning.billing.util.dao;
+import java.util.Iterator;
import java.util.List;
import org.skife.jdbi.v2.sqlobject.Bind;
@@ -23,11 +24,11 @@ import org.skife.jdbi.v2.sqlobject.BindBean;
import org.skife.jdbi.v2.sqlobject.SqlQuery;
import org.skife.jdbi.v2.sqlobject.SqlUpdate;
import org.skife.jdbi.v2.sqlobject.customizers.Define;
-import org.skife.jdbi.v2.sqlobject.customizers.RegisterMapper;
+import org.skife.jdbi.v2.sqlobject.customizers.FetchSize;
import com.ning.billing.callcontext.InternalCallContext;
import com.ning.billing.callcontext.InternalTenantContext;
-import com.ning.billing.util.audit.AuditLog;
+import com.ning.billing.util.audit.dao.AuditLogModelDao;
import com.ning.billing.util.cache.Cachable;
import com.ning.billing.util.cache.Cachable.CacheType;
import com.ning.billing.util.cache.CachableKey;
@@ -39,11 +40,11 @@ import com.ning.billing.util.entity.dao.EntitySqlDaoStringTemplate;
* which is good enough: the cache will always get at least the initial CREATION audit log entry, which is the one
* we really care about (both for Analytics and for Kaui's endpoints). Besides, we do cache invalidation properly
* on our own node (see EntitySqlDaoWrapperInvocationHandler).
- *
+ * <p/>
* Note 2: in the queries below, tableName always refers to the TableName enum, not the actual table name (TableName.getTableName()).
*/
@EntitySqlDaoStringTemplate("/com/ning/billing/util/entity/dao/EntitySqlDao.sql.stg")
-@RegisterMapper(AuditLogMapper.class)
+// Note: @RegisterMapper annotation won't work here as we build the SqlObject via EntitySqlDao (annotations won't be inherited for JDBI)
public interface AuditSqlDao {
@SqlUpdate
@@ -51,15 +52,28 @@ public interface AuditSqlDao {
@BindBean final InternalCallContext context);
@SqlQuery
+ // Magic value to force MySQL to stream from the database
+ // See http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-implementation-notes.html (ResultSet)
+ @FetchSize(Integer.MIN_VALUE)
+ public Iterator<AuditLogModelDao> getAuditLogsForAccountRecordId(@BindBean final InternalTenantContext context);
+
+ @SqlQuery
+ // Magic value to force MySQL to stream from the database
+ // See http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-implementation-notes.html (ResultSet)
+ @FetchSize(Integer.MIN_VALUE)
+ public Iterator<AuditLogModelDao> getAuditLogsForTableNameAndAccountRecordId(@Bind("tableName") final String tableName,
+ @BindBean final InternalTenantContext context);
+
+ @SqlQuery
@Cachable(CacheType.AUDIT_LOG)
- public List<AuditLog> getAuditLogsForTargetRecordId(@CachableKey(1) @Bind("tableName") final String tableName,
- @CachableKey(2) @Bind("targetRecordId") final long targetRecordId,
- @BindBean final InternalTenantContext context);
+ public List<AuditLogModelDao> getAuditLogsForTargetRecordId(@CachableKey(1) @Bind("tableName") final String tableName,
+ @CachableKey(2) @Bind("targetRecordId") final long targetRecordId,
+ @BindBean final InternalTenantContext context);
@SqlQuery
@Cachable(CacheType.AUDIT_LOG_VIA_HISTORY)
- public List<AuditLog> getAuditLogsViaHistoryForTargetRecordId(@CachableKey(1) @Bind("tableName") final String historyTableName, /* Uppercased - used to find entries in audit_log table */
- @CachableKey(2) @Define("historyTableName") final String actualHistoryTableName, /* Actual table name, used in the inner join query */
- @CachableKey(3) @Bind("targetRecordId") final long targetRecordId,
- @BindBean final InternalTenantContext context);
+ public List<AuditLogModelDao> getAuditLogsViaHistoryForTargetRecordId(@CachableKey(1) @Bind("tableName") final String historyTableName, /* Uppercased - used to find entries in audit_log table */
+ @CachableKey(2) @Define("historyTableName") final String actualHistoryTableName, /* Actual table name, used in the inner join query */
+ @CachableKey(3) @Bind("targetRecordId") final long targetRecordId,
+ @BindBean final InternalTenantContext context);
}
diff --git a/util/src/main/java/com/ning/billing/util/dao/NonEntitySqlDao.java b/util/src/main/java/com/ning/billing/util/dao/NonEntitySqlDao.java
index 36d7811..07e88c1 100644
--- a/util/src/main/java/com/ning/billing/util/dao/NonEntitySqlDao.java
+++ b/util/src/main/java/com/ning/billing/util/dao/NonEntitySqlDao.java
@@ -54,4 +54,9 @@ public interface NonEntitySqlDao extends Transactional<NonEntitySqlDao>, CloseMe
@SqlQuery
public Long getHistoryTargetRecordId(@Bind("recordId") Long recordId, @Define("tableName") final String tableName);
+
+ @SqlQuery
+ public UUID getIdFromHistoryRecordId(@Bind("historyRecordId") Long historyRecordId,
+ @Define("tableName") String tableName,
+ @Define("historyTableName") String historyTableName);
}
diff --git a/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoStringTemplate.java b/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoStringTemplate.java
index 143f3bc..e70cfcd 100644
--- a/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoStringTemplate.java
+++ b/util/src/main/java/com/ning/billing/util/entity/dao/EntitySqlDaoStringTemplate.java
@@ -77,9 +77,11 @@ public @interface EntitySqlDaoStringTemplate {
final ParameterizedType type = (ParameterizedType) sqlObjectType.getGenericInterfaces()[i];
for (int j = 0; j < type.getActualTypeArguments().length; j++) {
final Type modelType = type.getActualTypeArguments()[j];
- final Class modelClazz = (Class) modelType;
- if (Entity.class.isAssignableFrom(modelClazz)) {
- query.registerMapper(new LowerToCamelBeanMapperFactory(modelClazz));
+ if (modelType instanceof Class) {
+ final Class modelClazz = (Class) modelType;
+ if (Entity.class.isAssignableFrom(modelClazz)) {
+ query.registerMapper(new LowerToCamelBeanMapperFactory(modelClazz));
+ }
}
}
}
diff --git a/util/src/main/resources/com/ning/billing/util/dao/NonEntitySqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/dao/NonEntitySqlDao.sql.stg
index 1969615..6b2b6af 100644
--- a/util/src/main/resources/com/ning/billing/util/dao/NonEntitySqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/dao/NonEntitySqlDao.sql.stg
@@ -73,3 +73,13 @@ where record_id = :recordId
;
>>
+getIdFromHistoryRecordId(tableName, historyTableName) ::= <<
+select
+ t.id
+from <tableName> t
+join <historyTableName> ht on ht.target_record_id = t.record_id
+where ht.record_id = :historyRecordId
+limit 1
+;
+>>
+
diff --git a/util/src/main/resources/com/ning/billing/util/entity/dao/EntitySqlDao.sql.stg b/util/src/main/resources/com/ning/billing/util/entity/dao/EntitySqlDao.sql.stg
index b89eb6d..6214825 100644
--- a/util/src/main/resources/com/ning/billing/util/entity/dao/EntitySqlDao.sql.stg
+++ b/util/src/main/resources/com/ning/billing/util/entity/dao/EntitySqlDao.sql.stg
@@ -341,6 +341,29 @@ values (
;
>>
+getAuditLogsForAccountRecordId() ::= <<
+select
+ <auditTableFields("t.")>
+from <auditTableName()> t
+where <accountRecordIdField("t.")> = :accountRecordId
+<andCheckSoftDeletionWithComma("t.")>
+<AND_CHECK_TENANT("t.")>
+order by t.table_name, <recordIdField("t.")> ASC
+;
+>>
+
+getAuditLogsForTableNameAndAccountRecordId() ::= <<
+select
+ <auditTableFields("t.")>
+from <auditTableName()> t
+where <accountRecordIdField("t.")> = :accountRecordId
+and t.table_name = :tableName
+<andCheckSoftDeletionWithComma("t.")>
+<AND_CHECK_TENANT("t.")>
+<defaultOrderBy("t.")>
+;
+>>
+
getAuditLogsForTargetRecordId() ::= <<
select
<auditTableFields("t.")>
diff --git a/util/src/test/java/com/ning/billing/dbi/DBIProvider.java b/util/src/test/java/com/ning/billing/dbi/DBIProvider.java
index 824e50e..2c30cba 100644
--- a/util/src/test/java/com/ning/billing/dbi/DBIProvider.java
+++ b/util/src/test/java/com/ning/billing/dbi/DBIProvider.java
@@ -22,6 +22,7 @@ import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.IDBI;
import org.skife.jdbi.v2.tweak.transactions.SerializableTransactionRunner;
+import com.ning.billing.util.dao.AuditLogModelDaoMapper;
import com.ning.billing.util.dao.DateTimeArgumentFactory;
import com.ning.billing.util.dao.DateTimeZoneArgumentFactory;
import com.ning.billing.util.dao.EnumArgumentFactory;
@@ -53,6 +54,7 @@ public class DBIProvider implements Provider<IDBI> {
dbi.registerArgumentFactory(new LocalDateArgumentFactory());
dbi.registerArgumentFactory(new EnumArgumentFactory());
dbi.registerMapper(new UuidMapper());
+ dbi.registerMapper(new AuditLogModelDaoMapper());
// Restart transactions in case of deadlocks
dbi.setTransactionHandler(new SerializableTransactionRunner());
diff --git a/util/src/test/java/com/ning/billing/util/audit/api/TestDefaultAuditUserApi.java b/util/src/test/java/com/ning/billing/util/audit/api/TestDefaultAuditUserApi.java
index 0861ac9..a50d378 100644
--- a/util/src/test/java/com/ning/billing/util/audit/api/TestDefaultAuditUserApi.java
+++ b/util/src/test/java/com/ning/billing/util/audit/api/TestDefaultAuditUserApi.java
@@ -16,35 +16,19 @@
package com.ning.billing.util.audit.api;
-import java.util.ArrayList;
import java.util.List;
-import java.util.Map;
import java.util.UUID;
-import org.mockito.Mockito;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import com.ning.billing.ObjectType;
-import com.ning.billing.entitlement.api.SubscriptionBundle;
-import com.ning.billing.subscription.api.timeline.BundleBaseTimeline;
-import com.ning.billing.invoice.api.Invoice;
-import com.ning.billing.invoice.api.InvoiceItem;
-import com.ning.billing.invoice.api.InvoicePayment;
-import com.ning.billing.payment.api.Payment;
-import com.ning.billing.payment.api.Refund;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.audit.AuditLog;
-import com.ning.billing.util.audit.AuditLogsForBundles;
-import com.ning.billing.util.audit.AuditLogsForInvoicePayments;
-import com.ning.billing.util.audit.AuditLogsForInvoices;
-import com.ning.billing.util.audit.AuditLogsForPayments;
-import com.ning.billing.util.audit.AuditLogsForRefunds;
import com.ning.billing.util.audit.AuditLogsTestBase;
import com.ning.billing.util.audit.dao.MockAuditDao;
import com.ning.billing.util.dao.TableName;
-import com.ning.billing.util.entity.Entity;
import com.google.common.collect.ImmutableList;
@@ -53,7 +37,6 @@ public class TestDefaultAuditUserApi extends AuditLogsTestBase {
private List<AuditLog> auditLogs;
private List<UUID> objectIds;
-
@Override
@BeforeClass(groups = "fast")
public void beforeClass() throws Exception {
@@ -61,7 +44,6 @@ public class TestDefaultAuditUserApi extends AuditLogsTestBase {
auditLogs = ImmutableList.<AuditLog>of(createAuditLog(), createAuditLog(), createAuditLog(), createAuditLog());
objectIds = ImmutableList.<UUID>of(UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID());
-
for (final TableName tableName : TableName.values()) {
for (final UUID objectId : objectIds) {
for (final AuditLog auditLog : auditLogs) {
@@ -72,66 +54,6 @@ public class TestDefaultAuditUserApi extends AuditLogsTestBase {
}
@Test(groups = "fast")
- public void testForBundles() throws Exception {
- final List<SubscriptionBundle> bundles = new ArrayList<SubscriptionBundle>();
- for (final UUID objectId : objectIds) {
- final SubscriptionBundle entity = Mockito.mock(SubscriptionBundle.class);
- Mockito.when(entity.getId()).thenReturn(objectId);
- bundles.add(entity);
- }
-
- for (final AuditLevel level : AuditLevel.values()) {
- final AuditLogsForBundles auditLogsForBundles = auditUserApi.getAuditLogsForBundles(bundles, level, callContext);
- verifyAuditLogs(auditLogsForBundles.getBundlesAuditLogs(), level);
- }
- }
-
- @Test(groups = "fast")
- public void testForInvoicePayments() throws Exception {
- final List<InvoicePayment> invoicePayments = createMocks(InvoicePayment.class);
-
- for (final AuditLevel level : AuditLevel.values()) {
- final AuditLogsForInvoicePayments auditLogsForInvoicePayments = auditUserApi.getAuditLogsForInvoicePayments(invoicePayments, level, callContext);
- verifyAuditLogs(auditLogsForInvoicePayments.getInvoicePaymentsAuditLogs(), level);
- }
- }
-
- @Test(groups = "fast")
- public void testForRefunds() throws Exception {
- final List<Refund> refunds = createMocks(Refund.class);
-
- for (final AuditLevel level : AuditLevel.values()) {
- final AuditLogsForRefunds auditLogsForRefunds = auditUserApi.getAuditLogsForRefunds(refunds, level, callContext);
- verifyAuditLogs(auditLogsForRefunds.getRefundsAuditLogs(), level);
- }
- }
-
- @Test(groups = "fast")
- public void testForPayments() throws Exception {
- final List<Payment> payments = createMocks(Payment.class);
-
- for (final AuditLevel level : AuditLevel.values()) {
- final AuditLogsForPayments auditLogsForPayments = auditUserApi.getAuditLogsForPayments(payments, level, callContext);
- verifyAuditLogs(auditLogsForPayments.getPaymentsAuditLogs(), level);
- }
- }
-
- @Test(groups = "fast")
- public void testForInvoices() throws Exception {
- final List<Invoice> invoices = createMocks(Invoice.class);
- final List<InvoiceItem> invoiceItems = createMocks(InvoiceItem.class);
- for (final Invoice invoice : invoices) {
- Mockito.when(invoice.getInvoiceItems()).thenReturn(invoiceItems);
- }
-
- for (final AuditLevel level : AuditLevel.values()) {
- final AuditLogsForInvoices auditLogsForInvoices = auditUserApi.getAuditLogsForInvoices(invoices, level, callContext);
- verifyAuditLogs(auditLogsForInvoices.getInvoiceAuditLogs(), level);
- verifyAuditLogs(auditLogsForInvoices.getInvoiceItemsAuditLogs(), level);
- }
- }
-
- @Test(groups = "fast")
public void testForObject() throws Exception {
for (final ObjectType objectType : ObjectType.values()) {
for (final UUID objectId : objectIds) {
@@ -147,34 +69,4 @@ public class TestDefaultAuditUserApi extends AuditLogsTestBase {
}
}
}
-
- private void verifyAuditLogs(final Map<UUID, List<AuditLog>> objectsAuditLogs, final AuditLevel level) {
- Assert.assertEquals(objectsAuditLogs.size(), objectIds.size());
-
- if (AuditLevel.NONE.equals(level)) {
- for (final UUID objectId : objectIds) {
- Assert.assertEquals(objectsAuditLogs.get(objectId).size(), 0);
- }
- } else if (AuditLevel.MINIMAL.equals(level)) {
- for (final UUID objectId : objectIds) {
- Assert.assertEquals(objectsAuditLogs.get(objectId).size(), 1);
- Assert.assertEquals(objectsAuditLogs.get(objectId).get(0), auditLogs.get(0));
- }
- } else {
- for (final UUID objectId : objectIds) {
- Assert.assertEquals(objectsAuditLogs.get(objectId), auditLogs);
- }
- }
- }
-
- private <T extends Entity> List<T> createMocks(final Class<T> clazz) {
- final List<T> entities = new ArrayList<T>();
- for (final UUID objectId : objectIds) {
- final T entity = Mockito.mock(clazz);
- Mockito.when(entity.getId()).thenReturn(objectId);
- entities.add(entity);
- }
-
- return entities;
- }
}
diff --git a/util/src/test/java/com/ning/billing/util/audit/dao/MockAuditDao.java b/util/src/test/java/com/ning/billing/util/audit/dao/MockAuditDao.java
index 56d2349..b6982ee 100644
--- a/util/src/test/java/com/ning/billing/util/audit/dao/MockAuditDao.java
+++ b/util/src/test/java/com/ning/billing/util/audit/dao/MockAuditDao.java
@@ -22,9 +22,11 @@ import java.util.List;
import java.util.Map;
import java.util.UUID;
+import com.ning.billing.callcontext.InternalTenantContext;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.audit.AuditLog;
-import com.ning.billing.callcontext.InternalTenantContext;
+import com.ning.billing.util.audit.DefaultAccountAuditLogs;
+import com.ning.billing.util.audit.DefaultAccountAuditLogsForObjectType;
import com.ning.billing.util.dao.TableName;
import com.google.common.base.Objects;
@@ -51,6 +53,16 @@ public class MockAuditDao implements AuditDao {
}
@Override
+ public DefaultAccountAuditLogs getAuditLogsForAccountRecordId(final AuditLevel auditLevel, final InternalTenantContext context) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DefaultAccountAuditLogsForObjectType getAuditLogsForAccountRecordId(final TableName tableName, final AuditLevel auditLevel, final InternalTenantContext context) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
public List<AuditLog> getAuditLogsForId(final TableName tableName, final UUID objectId, final AuditLevel auditLevel, final InternalTenantContext context) {
final Map<UUID, List<AuditLog>> auditLogsForTableName = auditLogsForTables.get(tableName);
if (auditLogsForTableName == null) {
diff --git a/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java b/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java
index 3374bfd..d8f837a 100644
--- a/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java
+++ b/util/src/test/java/com/ning/billing/util/audit/dao/TestDefaultAuditDao.java
@@ -29,6 +29,8 @@ import com.ning.billing.util.UtilTestSuiteWithEmbeddedDB;
import com.ning.billing.util.api.AuditLevel;
import com.ning.billing.util.api.TagApiException;
import com.ning.billing.util.api.TagDefinitionApiException;
+import com.ning.billing.util.audit.AccountAuditLogs;
+import com.ning.billing.util.audit.AccountAuditLogsForObjectType;
import com.ning.billing.util.audit.AuditLog;
import com.ning.billing.util.audit.ChangeType;
import com.ning.billing.util.dao.TableName;
@@ -63,6 +65,12 @@ public class TestDefaultAuditDao extends UtilTestSuiteWithEmbeddedDB {
for (final AuditLevel level : AuditLevel.values()) {
final List<AuditLog> auditLogs = auditDao.getAuditLogsForId(TableName.TAG, tag.getId(), level, internalCallContext);
verifyAuditLogsForTag(auditLogs, level);
+
+ final AccountAuditLogs accountAuditLogs = auditDao.getAuditLogsForAccountRecordId(level, internalCallContext);
+ verifyAuditLogsForTag(accountAuditLogs.getAuditLogs(ObjectType.TAG).getAuditLogs(tag.getId()), level);
+
+ final AccountAuditLogsForObjectType accountAuditLogsForObjectType = auditDao.getAuditLogsForAccountRecordId(TableName.TAG, level, internalCallContext);
+ verifyAuditLogsForTag(accountAuditLogsForObjectType.getAuditLogs(tag.getId()), level);
}
}
diff --git a/util/src/test/java/com/ning/billing/util/audit/TestDefaultAuditLog.java b/util/src/test/java/com/ning/billing/util/audit/TestDefaultAuditLog.java
index b519df5..785b062 100644
--- a/util/src/test/java/com/ning/billing/util/audit/TestDefaultAuditLog.java
+++ b/util/src/test/java/com/ning/billing/util/audit/TestDefaultAuditLog.java
@@ -21,12 +21,14 @@ import java.util.UUID;
import org.testng.Assert;
import org.testng.annotations.Test;
+import com.ning.billing.ObjectType;
+import com.ning.billing.callcontext.DefaultCallContext;
+import com.ning.billing.clock.ClockMock;
import com.ning.billing.util.UtilTestSuiteNoDB;
+import com.ning.billing.util.audit.dao.AuditLogModelDao;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.CallOrigin;
-import com.ning.billing.callcontext.DefaultCallContext;
import com.ning.billing.util.callcontext.UserType;
-import com.ning.billing.clock.ClockMock;
import com.ning.billing.util.dao.EntityAudit;
import com.ning.billing.util.dao.TableName;
@@ -47,7 +49,7 @@ public class TestDefaultAuditLog extends UtilTestSuiteNoDB {
final ClockMock clock = new ClockMock();
final CallContext callContext = new DefaultCallContext(tenantId, userName, callOrigin, userType, userToken, clock);
- final AuditLog auditLog = new DefaultAuditLog(entityAudit, callContext);
+ final AuditLog auditLog = new DefaultAuditLog(new AuditLogModelDao(entityAudit, callContext), ObjectType.ACCOUNT_EMAIL, UUID.randomUUID());
Assert.assertEquals(auditLog.getChangeType(), changeType);
Assert.assertNull(auditLog.getComment());
Assert.assertNotNull(auditLog.getCreatedDate());
@@ -71,15 +73,15 @@ public class TestDefaultAuditLog extends UtilTestSuiteNoDB {
final ClockMock clock = new ClockMock();
final CallContext callContext = new DefaultCallContext(tenantId, userName, callOrigin, userType, userToken, clock);
- final AuditLog auditLog = new DefaultAuditLog(entityAudit, callContext);
+ final AuditLogModelDao auditLog = new AuditLogModelDao(entityAudit, callContext);
Assert.assertEquals(auditLog, auditLog);
- final AuditLog sameAuditLog = new DefaultAuditLog(entityAudit, callContext);
+ final AuditLogModelDao sameAuditLog = new AuditLogModelDao(entityAudit, callContext);
Assert.assertEquals(sameAuditLog, auditLog);
clock.addMonths(1);
final CallContext otherCallContext = new DefaultCallContext(tenantId, userName, callOrigin, userType, userToken, clock);
- final AuditLog otherAuditLog = new DefaultAuditLog(entityAudit, otherCallContext);
+ final AuditLogModelDao otherAuditLog = new AuditLogModelDao(entityAudit, otherCallContext);
Assert.assertNotEquals(otherAuditLog, auditLog);
}
}