killbill-aplcache

Details

diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
index 1cb7ffc..36f5347 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlement.java
@@ -71,11 +71,20 @@ import org.killbill.notificationq.api.NotificationEvent;
 import org.killbill.notificationq.api.NotificationQueue;
 import org.killbill.notificationq.api.NotificationQueueService;
 import org.killbill.notificationq.api.NotificationQueueService.NoSuchNotificationQueue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.collect.ImmutableList;
 
+import static org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logCancelEntitlement;
+import static org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logChangePlan;
+import static org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logUncancelEntitlement;
+import static org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logUpdateBCD;
+
 public class DefaultEntitlement extends EntityBase implements Entitlement {
 
+    private Logger log = LoggerFactory.getLogger(DefaultEntitlement.class);
+
     private final SecurityApi securityApi;
     protected final EventsStreamBuilder eventsStreamBuilder;
     protected final EntitlementDateHelper dateHelper;
@@ -287,6 +296,8 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
     @Override
     public Entitlement cancelEntitlementWithPolicy(final EntitlementActionPolicy entitlementPolicy, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
 
+        logCancelEntitlement(log, this, null, null, entitlementPolicy, null);
+
         // Get the latest state from disk - required to have the latest CTD
         refresh(callContext);
 
@@ -297,6 +308,8 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
     @Override
     public Entitlement cancelEntitlementWithDate(@Nullable final LocalDate entitlementEffectiveDate, final boolean overrideBillingEffectiveDate, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
 
+        logCancelEntitlement(log, this, entitlementEffectiveDate, overrideBillingEffectiveDate, null, null);
+
         checkForPermissions(Permission.ENTITLEMENT_CAN_CANCEL, callContext);
 
         // Get the latest state from disk
@@ -360,6 +373,8 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
     @Override
     public void uncancelEntitlement(final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
 
+        logUncancelEntitlement(log, this);
+
         checkForPermissions(Permission.ENTITLEMENT_CAN_CANCEL, callContext);
 
         // Get the latest state from disk
@@ -422,6 +437,9 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
 
     @Override
     public Entitlement cancelEntitlementWithPolicyOverrideBillingPolicy(final EntitlementActionPolicy entitlementPolicy, final BillingActionPolicy billingPolicy, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
+
+        logCancelEntitlement(log, this, null, null, entitlementPolicy, billingPolicy);
+
         // Get the latest state from disk - required to have the latest CTD
         refresh(callContext);
 
@@ -433,6 +451,8 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
     @Override
     public Entitlement cancelEntitlementWithDateOverrideBillingPolicy(@Nullable final LocalDate entitlementEffectiveDate, final BillingActionPolicy billingPolicy, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
 
+        logCancelEntitlement(log, this, entitlementEffectiveDate, null, null, billingPolicy);
+
         checkForPermissions(Permission.ENTITLEMENT_CAN_CANCEL, callContext);
 
         // Get the latest state from disk
@@ -508,6 +528,8 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
     @Override
     public Entitlement changePlan(final String productName, final BillingPeriod billingPeriod, final String priceList, final List<PlanPhasePriceOverride> overrides, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
 
+        logChangePlan(log, this, productName, billingPeriod, priceList, overrides, null, null);
+
         checkForPermissions(Permission.ENTITLEMENT_CAN_CHANGE_PLAN, callContext);
 
         // Get the latest state from disk
@@ -570,6 +592,8 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
     @Override
     public Entitlement changePlanWithDate(final String productName, final BillingPeriod billingPeriod, final String priceList, final List<PlanPhasePriceOverride> overrides, @Nullable final LocalDate effectiveDate, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
 
+        logChangePlan(log, this, productName, billingPeriod, priceList, overrides, effectiveDate, null);
+
         checkForPermissions(Permission.ENTITLEMENT_CAN_CHANGE_PLAN, callContext);
 
         // Get the latest state from disk
@@ -634,6 +658,8 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
     @Override
     public Entitlement changePlanOverrideBillingPolicy(final String productName, final BillingPeriod billingPeriod, final String priceList, final List<PlanPhasePriceOverride> overrides, final LocalDate entitlementEffectiveDate, final BillingActionPolicy actionPolicy, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
 
+        logChangePlan(log, this, productName, billingPeriod, priceList, overrides, entitlementEffectiveDate, actionPolicy);
+
         checkForPermissions(Permission.ENTITLEMENT_CAN_CHANGE_PLAN, callContext);
 
         // Get the latest state from disk
@@ -696,6 +722,9 @@ public class DefaultEntitlement extends EntityBase implements Entitlement {
 
     @Override
     public void updateBCD(final int newBCD, @Nullable final LocalDate effectiveFromDate, final CallContext callContext) throws EntitlementApiException {
+
+        logUpdateBCD(log, this, newBCD, effectiveFromDate);
+
         final InternalCallContext context = internalCallContextFactory.createInternalCallContext(getAccountId(), callContext);
         try {
             subscriptionInternalApi.updateBCD(getId(), newBCD, effectiveFromDate, context);
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
index 4cab8ea..26290f9 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultEntitlementApi.java
@@ -47,6 +47,7 @@ import org.killbill.billing.entitlement.block.BlockingChecker;
 import org.killbill.billing.entitlement.dao.BlockingStateDao;
 import org.killbill.billing.entitlement.engine.core.EntitlementUtils;
 import org.killbill.billing.entitlement.engine.core.EventsStreamBuilder;
+import org.killbill.billing.entitlement.logging.EntitlementLoggingHelper;
 import org.killbill.billing.entitlement.plugin.api.EntitlementContext;
 import org.killbill.billing.entitlement.plugin.api.OperationType;
 import org.killbill.billing.junction.DefaultBlockingState;
@@ -71,8 +72,14 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
+import static org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logCreateEntitlement;
+import static org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logCreateEntitlementWithAOs;
+import static org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logPauseResumeEntitlement;
+import static org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logTransferEntitlement;
+
 public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements EntitlementApi {
 
+
     public static final String ENT_STATE_START = "ENT_STARTED";
     public static final String ENT_STATE_BLOCKED = "ENT_BLOCKED";
     public static final String ENT_STATE_CLEAR = "ENT_CLEAR";
@@ -121,6 +128,8 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements 
                                              @Nullable final LocalDate entitlementEffectiveDate, @Nullable  LocalDate billingEffectiveDate, final boolean isMigrated,
                                              final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
 
+        logCreateEntitlement(log, null, planPhaseSpecifier, overrides, entitlementEffectiveDate, billingEffectiveDate);
+
         final EntitlementSpecifier entitlementSpecifier = new DefaultEntitlementSpecifier(planPhaseSpecifier, overrides);
         final List<EntitlementSpecifier> entitlementSpecifierList = new ArrayList<EntitlementSpecifier>();
         entitlementSpecifierList.add(entitlementSpecifier);
@@ -179,6 +188,9 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements 
                                                        final Iterable<PluginProperty> properties, final CallContext callContext)
             throws EntitlementApiException {
 
+        logCreateEntitlementWithAOs(log, externalKey, entitlementSpecifiers, entitlementEffectiveDate, billingEffectiveDate);
+
+
         final EntitlementSpecifier baseSpecifier = Iterables.tryFind(entitlementSpecifiers, new Predicate<EntitlementSpecifier>() {
             @Override
             public boolean apply(final EntitlementSpecifier specifier) {
@@ -247,6 +259,9 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements 
     public Entitlement addEntitlement(final UUID bundleId, final PlanPhaseSpecifier planPhaseSpecifier, final List<PlanPhasePriceOverride> overrides, @Nullable final LocalDate entitlementEffectiveDate, @Nullable final LocalDate billingEffectiveDate,
             final boolean isMigrated, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
 
+
+        logCreateEntitlement(log, bundleId, planPhaseSpecifier, overrides, entitlementEffectiveDate, billingEffectiveDate);
+
         final EntitlementSpecifier entitlementSpecifier = new DefaultEntitlementSpecifier(planPhaseSpecifier, overrides);
         final List<EntitlementSpecifier> entitlementSpecifierList = new ArrayList<EntitlementSpecifier>();
         entitlementSpecifierList.add(entitlementSpecifier);
@@ -372,6 +387,8 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements 
     @Override
     public void pause(final UUID bundleId, final LocalDate localEffectiveDate, final Iterable<PluginProperty> properties, final CallContext context) throws EntitlementApiException {
 
+        logPauseResumeEntitlement(log, "Pause", bundleId, localEffectiveDate);
+
         final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(bundleId, ObjectType.BUNDLE, context);
         super.pause(bundleId, localEffectiveDate, properties, contextWithValidAccountRecordId);
     }
@@ -379,6 +396,8 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements 
     @Override
     public void resume(final UUID bundleId, final LocalDate localEffectiveDate, final Iterable<PluginProperty> properties, final CallContext context) throws EntitlementApiException {
 
+        logPauseResumeEntitlement(log, "Resume", bundleId, localEffectiveDate);
+
         final InternalCallContext contextWithValidAccountRecordId = internalCallContextFactory.createInternalCallContext(bundleId, ObjectType.BUNDLE, context);
         super.resume(bundleId, localEffectiveDate, properties, contextWithValidAccountRecordId);
 
@@ -392,6 +411,8 @@ public class DefaultEntitlementApi extends DefaultEntitlementApiBase implements 
     @Override
     public UUID transferEntitlementsOverrideBillingPolicy(final UUID sourceAccountId, final UUID destAccountId, final String externalKey, @Nullable final LocalDate effectiveDate, final BillingActionPolicy billingPolicy, final Iterable<PluginProperty> properties, final CallContext context) throws EntitlementApiException {
 
+        logTransferEntitlement(log, sourceAccountId, destAccountId, externalKey, effectiveDate, billingPolicy);
+
         final EntitlementContext pluginContext = new DefaultEntitlementContext(OperationType.TRANSFER_BUNDLE,
                                                                                sourceAccountId,
                                                                                destAccountId,
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java
index a5e1c5c..a6fbfb9 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/DefaultSubscriptionApi.java
@@ -71,6 +71,8 @@ import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Ordering;
 
+import static org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logAddBlockingState;
+import static org.killbill.billing.entitlement.logging.EntitlementLoggingHelper.logUpdateExternalKey;
 import static org.killbill.billing.util.entity.dao.DefaultPaginationHelper.getEntityPaginationNoException;
 
 public class DefaultSubscriptionApi implements SubscriptionApi {
@@ -104,7 +106,6 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
     private final EntitlementPluginExecution pluginExecution;
     private final BlockingStateDao blockingStateDao;
 
-
     @Inject
     public DefaultSubscriptionApi(final AccountInternalApi accountApi,
                                   final EntitlementInternalApi entitlementInternalApi,
@@ -262,6 +263,9 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
 
     @Override
     public void updateExternalKey(final UUID bundleId, final String newExternalKey, final CallContext callContext) throws EntitlementApiException {
+
+        logUpdateExternalKey(log, bundleId, newExternalKey);
+
         final InternalCallContext internalCallContext = internalCallContextFactory.createInternalCallContextWithoutAccountRecordId(callContext);
 
         final SubscriptionBaseBundle bundle;
@@ -304,6 +308,8 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
     @Override
     public void addBlockingState(final BlockingState inputBlockingState, @Nullable final LocalDate inputEffectiveDate, final Iterable<PluginProperty> properties, final CallContext callContext) throws EntitlementApiException {
 
+        logAddBlockingState(log, inputBlockingState, inputEffectiveDate);
+
         // This is in no way an exhaustive arg validation, but to to ensure plugin would not hijack private entitlement state or service name
         if (inputBlockingState.getService() == null || inputBlockingState.getService().equals(EntitlementService.ENTITLEMENT_SERVICE_NAME)) {
             throw new EntitlementApiException(ErrorCode.SUB_BLOCKING_STATE_INVALID_ARG, "Need to specify a valid serviceName");
@@ -392,7 +398,7 @@ public class DefaultSubscriptionApi implements SubscriptionApi {
 
             final ImmutableAccountData account = accountApi.getImmutableAccountDataById(accountId, internalTenantContextWithValidAccountRecordId);
 
-            final Iterable<BlockingState> filteredByTypes = typeFilter != null  && !typeFilter.isEmpty() ?
+            final Iterable<BlockingState> filteredByTypes = typeFilter != null && !typeFilter.isEmpty() ?
                                                             Iterables.filter(allBlockingStates, new Predicate<BlockingState>() {
                                                                 @Override
                                                                 public boolean apply(final BlockingState input) {
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementApiBase.java b/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementApiBase.java
index b8df661..3044aca 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementApiBase.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/api/svcs/DefaultEntitlementApiBase.java
@@ -17,7 +17,6 @@
 
 package org.killbill.billing.entitlement.api.svcs;
 
-import java.io.IOException;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -28,15 +27,11 @@ import javax.annotation.Nullable;
 
 import org.joda.time.DateTime;
 import org.joda.time.LocalDate;
-import org.killbill.billing.ErrorCode;
-import org.killbill.billing.account.api.AccountApiException;
 import org.killbill.billing.account.api.AccountInternalApi;
-import org.killbill.billing.account.api.ImmutableAccountData;
 import org.killbill.billing.callcontext.InternalCallContext;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.entitlement.AccountEntitlements;
 import org.killbill.billing.entitlement.AccountEventsStreams;
-import org.killbill.billing.entitlement.DefaultEntitlementService;
 import org.killbill.billing.entitlement.EntitlementService;
 import org.killbill.billing.entitlement.EventsStream;
 import org.killbill.billing.entitlement.api.BlockingState;
@@ -52,8 +47,6 @@ import org.killbill.billing.entitlement.api.EntitlementPluginExecution;
 import org.killbill.billing.entitlement.api.EntitlementPluginExecution.WithEntitlementPlugin;
 import org.killbill.billing.entitlement.block.BlockingChecker;
 import org.killbill.billing.entitlement.dao.BlockingStateDao;
-import org.killbill.billing.entitlement.engine.core.EntitlementNotificationKey;
-import org.killbill.billing.entitlement.engine.core.EntitlementNotificationKeyAction;
 import org.killbill.billing.entitlement.engine.core.EntitlementUtils;
 import org.killbill.billing.entitlement.engine.core.EventsStreamBuilder;
 import org.killbill.billing.entitlement.plugin.api.EntitlementContext;
@@ -64,14 +57,10 @@ import org.killbill.billing.security.api.SecurityApi;
 import org.killbill.billing.subscription.api.SubscriptionBase;
 import org.killbill.billing.subscription.api.SubscriptionBaseInternalApi;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseApiException;
-import org.killbill.billing.subscription.api.user.SubscriptionBaseBundle;
 import org.killbill.billing.util.callcontext.InternalCallContextFactory;
 import org.killbill.bus.api.PersistentBus;
 import org.killbill.clock.Clock;
-import org.killbill.notificationq.api.NotificationEvent;
-import org.killbill.notificationq.api.NotificationQueue;
 import org.killbill.notificationq.api.NotificationQueueService;
-import org.killbill.notificationq.api.NotificationQueueService.NoSuchNotificationQueue;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -79,7 +68,7 @@ import com.google.common.collect.ImmutableList;
 
 public class DefaultEntitlementApiBase {
 
-    private static final Logger log = LoggerFactory.getLogger(DefaultEntitlementApiBase.class);
+    protected static final Logger log = LoggerFactory.getLogger(DefaultEntitlementApiBase.class);
 
     protected final EntitlementApi entitlementApi;
     protected final AccountInternalApi accountApi;
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/logging/EntitlementLoggingHelper.java b/entitlement/src/main/java/org/killbill/billing/entitlement/logging/EntitlementLoggingHelper.java
new file mode 100644
index 0000000..4b54799
--- /dev/null
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/logging/EntitlementLoggingHelper.java
@@ -0,0 +1,371 @@
+/*
+ * Copyright 2014-2016 Groupon, Inc
+ * Copyright 2014-2016 The Billing Project, LLC
+ *
+ * The Billing Project licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.entitlement.logging;
+
+import java.util.List;
+import java.util.UUID;
+
+import org.joda.time.LocalDate;
+import org.killbill.billing.catalog.api.BillingActionPolicy;
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.PlanPhasePriceOverride;
+import org.killbill.billing.catalog.api.PlanPhaseSpecifier;
+import org.killbill.billing.entitlement.api.BlockingState;
+import org.killbill.billing.entitlement.api.Entitlement;
+import org.killbill.billing.entitlement.api.Entitlement.EntitlementActionPolicy;
+import org.killbill.billing.entitlement.api.EntitlementSpecifier;
+import org.slf4j.Logger;
+
+public abstract class EntitlementLoggingHelper {
+
+    public static void logCreateEntitlement(final Logger log,
+                                            final UUID bundleId,
+                                            final PlanPhaseSpecifier spec,
+                                            final List<PlanPhasePriceOverride> overrides,
+                                            final LocalDate entitlementDate,
+                                            final LocalDate billingDate) {
+
+        if (log.isInfoEnabled()) {
+            final StringBuilder logLine = new StringBuilder("Create ")
+                    .append(bundleId != null ? " BP " : " AO ")
+                    .append("Entitlement: ");
+
+            if (bundleId != null) {
+                logLine.append(", bundleId='")
+                       .append(bundleId)
+                       .append("'");
+            }
+            logPlanPhaseSpecifier(logLine, spec, true, true);
+            if (overrides != null && !overrides.isEmpty()) {
+                logPlanPhasePriceOverrides(logLine, overrides);
+            }
+            if (entitlementDate != null) {
+                logLine.append(", entDate='")
+                       .append(entitlementDate)
+                       .append("'");
+            }
+            if (billingDate != null) {
+                logLine.append(", billDate='")
+                       .append(billingDate)
+                       .append("'");
+            }
+            log.info(logLine.toString());
+        }
+    }
+
+    public static void logCreateEntitlementWithAOs(final Logger log,
+                                                   final String externalKey,
+                                                   final Iterable<EntitlementSpecifier> entitlementSpecifiers,
+                                                   final LocalDate entitlementDate,
+                                                   final LocalDate billingDate) {
+        if (log.isInfoEnabled()) {
+            final StringBuilder logLine = new StringBuilder("Create Entitlements: ");
+
+            if (externalKey != null) {
+                logLine.append("key='")
+                       .append(externalKey)
+                       .append("'");
+            }
+            if (entitlementDate != null) {
+                logLine.append(", entDate='")
+                       .append(entitlementDate)
+                       .append("'");
+            }
+            if (billingDate != null) {
+                logLine.append(", billDate='")
+                       .append(billingDate)
+                       .append("'");
+            }
+            logEntitlementSpecifier(logLine, entitlementSpecifiers);
+            log.info(logLine.toString());
+        }
+
+    }
+
+    public static void logPauseResumeEntitlement(final Logger log,
+                                                 final String op,
+                                                 final UUID bundleId,
+                                                 final LocalDate effectiveDate) {
+        if (log.isInfoEnabled()) {
+            final StringBuilder logLine = new StringBuilder(op)
+                    .append(" Entitlement: ");
+
+            if (bundleId != null) {
+                logLine.append(", bundleId='")
+                       .append(bundleId)
+                       .append("'");
+            }
+            if (effectiveDate != null) {
+                logLine.append(", date='")
+                       .append(effectiveDate)
+                       .append("'");
+            }
+            log.info(logLine.toString());
+        }
+    }
+
+    public static void logTransferEntitlement(final Logger log,
+                                              final UUID sourceAccountId,
+                                              final UUID destAccountId,
+                                              final String externalKey,
+                                              final LocalDate effectiveDate,
+                                              final BillingActionPolicy billingPolicy) {
+
+        if (log.isInfoEnabled()) {
+            final StringBuilder logLine = new StringBuilder("Transfer Entitlement: ");
+            if (sourceAccountId != null) {
+                logLine.append(", src='")
+                       .append(sourceAccountId)
+                       .append("'");
+            }
+            if (destAccountId != null) {
+                logLine.append(", dst='")
+                       .append(destAccountId)
+                       .append("'");
+            }
+            if (externalKey != null) {
+                logLine.append(", key='")
+                       .append(externalKey)
+                       .append("'");
+            }
+            if (effectiveDate != null) {
+                logLine.append(", date='")
+                       .append(effectiveDate)
+                       .append("'");
+            }
+            if (effectiveDate != null) {
+                logLine.append(", policy='")
+                       .append(billingPolicy)
+                       .append("'");
+            }
+            log.info(logLine.toString());
+        }
+    }
+
+    public static void logCancelEntitlement(final Logger log, final Entitlement entitlement, final LocalDate entitlementEffectiveDate, final Boolean overrideBillingEffectiveDate, final EntitlementActionPolicy entitlementPolicy, final BillingActionPolicy billingPolicy) {
+        if (log.isInfoEnabled()) {
+            final StringBuilder logLine = new StringBuilder("Cancel Entitlement: ")
+                    .append(" id = '")
+                    .append(entitlement.getId())
+                    .append("'");
+            if (entitlementEffectiveDate != null) {
+                logLine.append(", entDate='")
+                       .append(entitlementEffectiveDate)
+                       .append("'");
+            }
+            if (overrideBillingEffectiveDate != null) {
+                logLine.append(", overrideBillDate='")
+                       .append(overrideBillingEffectiveDate)
+                       .append("'");
+            }
+            if (entitlementPolicy != null) {
+                logLine.append(", entPolicy='")
+                       .append(entitlementPolicy)
+                       .append("'");
+            }
+            if (billingPolicy != null) {
+                logLine.append(", billPolicy='")
+                       .append(billingPolicy)
+                       .append("'");
+            }
+            log.info(logLine.toString());
+        }
+    }
+
+    public static void logUncancelEntitlement(final Logger log, final Entitlement entitlement) {
+        if (log.isInfoEnabled()) {
+            final StringBuilder logLine = new StringBuilder("Uncancel Entitlement: ")
+                    .append(" id = '")
+                    .append(entitlement.getId())
+                    .append("'");
+            log.info(logLine.toString());
+        }
+    }
+
+    public static void logChangePlan(final Logger log, final Entitlement entitlement, String productName, final BillingPeriod billingPeriod, final String priceList,
+                                     final List<PlanPhasePriceOverride> overrides, final LocalDate entitlementEffectiveDate, final BillingActionPolicy actionPolicy) {
+        if (log.isInfoEnabled()) {
+            final StringBuilder logLine = new StringBuilder("Change Entitlement Plan: ")
+                    .append(" id = '")
+                    .append(entitlement.getId())
+                    .append("'");
+            if (entitlementEffectiveDate != null) {
+                logLine.append(", entDate='")
+                       .append(entitlementEffectiveDate)
+                       .append("'");
+            }
+            if (productName != null) {
+                logLine.append(", product='")
+                       .append(productName)
+                       .append("'");
+            }
+            if (billingPeriod != null) {
+                logLine.append(", billingPeriod='")
+                       .append(billingPeriod)
+                       .append("'");
+            }
+            if (priceList != null) {
+                logLine.append(", priceList='")
+                       .append(priceList)
+                       .append("'");
+            }
+            logPlanPhasePriceOverrides(logLine, overrides);
+            if (actionPolicy != null) {
+                logLine.append(", actionPolicy='")
+                       .append(actionPolicy)
+                       .append("'");
+            }
+            log.info(logLine.toString());
+        }
+    }
+
+    public static void logUpdateBCD(final Logger log, final Entitlement entitlement, final int newBCD, final LocalDate effectiveFromDate) {
+        if (log.isInfoEnabled()) {
+            final StringBuilder logLine = new StringBuilder("Update Entitlement BCD: ")
+                    .append(" id = '")
+                    .append(entitlement.getId())
+                    .append("'");
+
+            logLine.append(", newBCD='")
+                   .append(newBCD)
+                   .append("'");
+            if (effectiveFromDate != null) {
+                logLine.append(", date='")
+                       .append(effectiveFromDate)
+                       .append("'");
+            }
+            log.info(logLine.toString());
+        }
+    }
+
+    public static void logUpdateExternalKey(final Logger log, final UUID bundleId, final String newExternalKey) {
+        if (log.isInfoEnabled()) {
+            final StringBuilder logLine = new StringBuilder("Update Entitlement Key: ");
+            if (bundleId != null) {
+                logLine.append(", bundleId='")
+                       .append(bundleId)
+                       .append("'");
+            }
+            if (newExternalKey != null) {
+                logLine.append(", key='")
+                       .append(newExternalKey)
+                       .append("'");
+            }
+            log.info(logLine.toString());
+        }
+    }
+
+    public static void logAddBlockingState(final Logger log, final BlockingState inputBlockingState, final LocalDate inputEffectiveDate) {
+        if (log.isInfoEnabled()) {
+            final StringBuilder logLine = new StringBuilder("Add BlockingState Entitlement: ");
+            logBlockingState(logLine, inputBlockingState);
+            if (inputEffectiveDate != null) {
+                logLine.append(", date='")
+                       .append(inputEffectiveDate)
+                       .append("'");
+            }
+            log.info(logLine.toString());
+        }
+    }
+
+    private static void logBlockingState(final StringBuilder logLine, final BlockingState blk) {
+        if (blk != null) {
+            logLine.append("blk='");
+            logLine.append(blk.getBlockedId() != null ? blk.getBlockedId() : "null");
+            logLine.append(":");
+            logLine.append(blk.getType() != null ? blk.getType() : "null");
+            logLine.append(":");
+            logLine.append(blk.getService() != null ? blk.getService() : "null");
+            logLine.append(":");
+            logLine.append(blk.getStateName() != null ? blk.getStateName() : "null");
+            logLine.append("'");
+        }
+    }
+
+    private static void logEntitlementSpecifier(final StringBuilder logLine, final Iterable<EntitlementSpecifier> entitlementSpecifiers) {
+        if (entitlementSpecifiers != null && entitlementSpecifiers.iterator().hasNext()) {
+            logLine.append(",'[");
+            boolean first = true;
+            for (EntitlementSpecifier cur : entitlementSpecifiers) {
+                if (!first) {
+                    logLine.append(",");
+                }
+                logPlanPhaseSpecifier(logLine, cur.getPlanPhaseSpecifier(), false, false);
+                logPlanPhasePriceOverrides(logLine, cur.getOverrides());
+                first = false;
+            }
+            logLine.append("]'");
+        }
+    }
+
+    private static void logPlanPhaseSpecifier(final StringBuilder logLine, final PlanPhaseSpecifier spec, boolean addComma, boolean addParentheseQuote) {
+        if (spec != null) {
+            if (addComma) {
+                logLine.append(", ");
+            }
+            logLine.append("spec=");
+            if (addParentheseQuote) {
+                logLine.append("'(");
+            }
+            logLine.append(spec.getProductCategory() != null ? spec.getProductCategory() : "null");
+            logLine.append(":");
+            logLine.append(spec.getProductName() != null ? spec.getProductName() : "null");
+            logLine.append(":");
+            logLine.append(spec.getBillingPeriod() != null ? spec.getBillingPeriod() : "null");
+            logLine.append(":");
+            logLine.append(spec.getPhaseType() != null ? spec.getPhaseType() : "null");
+            logLine.append(":");
+            logLine.append(spec.getPriceListName() != null ? spec.getPriceListName() : "null");
+            if (addParentheseQuote) {
+                logLine.append(")'");
+            }
+        }
+    }
+
+    private static void logPlanPhasePriceOverrides(final StringBuilder logLine, final List<PlanPhasePriceOverride> overrides) {
+        if (overrides != null && !overrides.isEmpty()) {
+            logLine.append(", overrides='[");
+            boolean first = true;
+            for (final PlanPhasePriceOverride cur : overrides) {
+                if (!first) {
+                    logLine.append(",");
+                }
+                logPlanPhasePriceOverride(logLine, cur);
+                first = false;
+            }
+            logLine.append("]'");
+
+        }
+    }
+
+    private static void logPlanPhasePriceOverride(final StringBuilder logLine, final PlanPhasePriceOverride override) {
+        if (override != null) {
+            logLine.append("(");
+            logPlanPhaseSpecifier(logLine, override.getPlanPhaseSpecifier(), false, false);
+            logLine.append(":");
+            logLine.append(override.getPhaseName() != null ? override.getPhaseName() : "null");
+            logLine.append(":");
+            logLine.append(override.getCurrency() != null ? override.getCurrency() : "null");
+            logLine.append(":");
+            logLine.append(override.getFixedPrice() != null ? override.getFixedPrice() : "null");
+            logLine.append(":");
+            logLine.append(override.getRecurringPrice() != null ? override.getRecurringPrice() : "null");
+            logLine.append(")");
+        }
+    }
+}