Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * 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.subscription.engine.dao;
  
  import java.util.Date;
  import java.util.HashMap;
  import java.util.List;
  import java.util.Map;
  import java.util.UUID;
  
  import  javax.annotation.Nullable;
  
  import org.slf4j.Logger;
  
  
 
 public class DefaultSubscriptionDao implements SubscriptionDao {
 
     private static final Logger log = LoggerFactory.getLogger(DefaultSubscriptionDao.class);
 
     private final Clock clock;
     private final AddonUtils addonUtils;
     private final PersistentBus eventBus;
     private final CatalogService catalogService;
 
     @Inject
     public DefaultSubscriptionDao(final IDBI dbifinal Clock clockfinal AddonUtils addonUtils,
                                   final NotificationQueueService notificationQueueServicefinal PersistentBus eventBusfinal CatalogService catalogService,
                                   final CacheControllerDispatcher cacheControllerDispatcherfinal NonEntityDao nonEntityDao) {
         this. = clock;
         this. = new EntitySqlDaoTransactionalJdbiWrapper(dbiclockcacheControllerDispatchernonEntityDao);
         this. = notificationQueueService;
         this. = addonUtils;
         this. = eventBus;
         this. = catalogService;
     }
 
     @Override
     public List<SubscriptionBaseBundlegetSubscriptionBundlesForAccountAndKey(final UUID accountIdfinal String bundleKeyfinal InternalTenantContext context) {
             @Override
             public List<SubscriptionBaseBundleinTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final List<SubscriptionBundleModelDaomodels = entitySqlDaoWrapperFactory.become(BundleSqlDao.class).getBundlesFromAccountAndKey(accountId.toString(), bundleKeycontext);
                 return new ArrayList<SubscriptionBaseBundle>(Collections2.transform(modelsnew Function<SubscriptionBundleModelDaoSubscriptionBaseBundle>() {
                     @Override
                     public SubscriptionBaseBundle apply(@Nullable final SubscriptionBundleModelDao input) {
                         return SubscriptionBundleModelDao.toSubscriptionbundle(input);
                     }
                 }));
             }
         });
     }
 
     @Override
     public List<SubscriptionBaseBundlegetSubscriptionBundleForAccount(final UUID accountIdfinal InternalTenantContext context) {
             @Override
             public List<SubscriptionBaseBundleinTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final List<SubscriptionBundleModelDaomodels = entitySqlDaoWrapperFactory.become(BundleSqlDao.class).getBundleFromAccount(accountId.toString(), context);
 
                 return new ArrayList<SubscriptionBaseBundle>(Collections2.transform(modelsnew Function<SubscriptionBundleModelDaoSubscriptionBaseBundle>() {
                     @Override
                     public SubscriptionBaseBundle apply(@Nullable final SubscriptionBundleModelDao input) {
                         return SubscriptionBundleModelDao.toSubscriptionbundle(input);
                     }
                 }));
             }
         });
     }
 
     @Override
     public SubscriptionBaseBundle getSubscriptionBundleFromId(final UUID bundleIdfinal InternalTenantContext context) {
             @Override
             public SubscriptionBaseBundle inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final SubscriptionBundleModelDao model = entitySqlDaoWrapperFactory.become(BundleSqlDao.class).getById(bundleId.toString(), context);
                 return SubscriptionBundleModelDao.toSubscriptionbundle(model);
             }
         });
     }
 
     @Override
     public List<SubscriptionBaseBundlegetSubscriptionBundlesForKey(final String bundleKeyfinal InternalTenantContext context) {
             @Override
             public List<SubscriptionBaseBundleinTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final List<SubscriptionBundleModelDaomodels = entitySqlDaoWrapperFactory.become(BundleSqlDao.class).getBundlesForKey(bundleKeycontext);
                 return new ArrayList<SubscriptionBaseBundle>(Collections2.transform(modelsnew Function<SubscriptionBundleModelDaoSubscriptionBaseBundle>() {
                     @Override
                     public SubscriptionBaseBundle apply(@Nullable final SubscriptionBundleModelDao input) {
                         return SubscriptionBundleModelDao.toSubscriptionbundle(input);
                     }
                 }));
             }
         });
     }
 
     @Override
     public Iterable<UUIDgetNonAOSubscriptionIdsForKey(final String bundleKeyfinal InternalTenantContext context) {
             @Override
             public Iterable<UUIDinTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
 
                 final BundleSqlDao bundleSqlDao = entitySqlDaoWrapperFactory.become(BundleSqlDao.class);
 
                 final List<SubscriptionBundleModelDaobundles = bundleSqlDao.getBundlesForKey(bundleKeycontext);
 
                 final SubscriptionSqlDao subscriptionSqlDao = entitySqlDaoWrapperFactory.become(SubscriptionSqlDao.class);
                 return Iterables.concat(Iterables.transform(bundlesnew Function<SubscriptionBundleModelDaoIterable<UUID>>() {
 
                     @Override
                     public Iterable<UUIDapply(final SubscriptionBundleModelDao cur) {
 
                         final List<SubscriptionModelDaosubscriptions = subscriptionSqlDao.getSubscriptionsFromBundleId(cur.getId().toString(), context);
 
                         final Iterable<SubscriptionModelDaononAddonSubscriptions = Iterables.filter(subscriptionsnew Predicate<SubscriptionModelDao>() {
                             @Override
                             public boolean apply(final SubscriptionModelDao input) {
                                 return input.getCategory() != .;
                             }
                         });
 
                         return Iterables.transform(nonAddonSubscriptionsnew Function<SubscriptionModelDaoUUID>() {
                             @Override
                             public UUID apply(final SubscriptionModelDao input) {
                                 return input.getId();
                             }
                         });
                     }
                 }));
             }
         });
     }
 
     @Override
             @Override
             public SubscriptionBaseBundle inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows EntityPersistenceException {
 
                 final SubscriptionBundleModelDao model = new SubscriptionBundleModelDao(bundle);
                 entitySqlDaoWrapperFactory.become(BundleSqlDao.class).create(modelcontext);
                 final SubscriptionBundleModelDao result = entitySqlDaoWrapperFactory.become(BundleSqlDao.class).getById(bundle.getId().toString(), context);
                 return SubscriptionBundleModelDao.toSubscriptionbundle(result);
             }
         });
     }
 
     @Override
     public UUID getAccountIdFromSubscriptionId(final UUID subscriptionIdfinal InternalTenantContext context) {
 
             @Override
             public UUID inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final SubscriptionModelDao subscriptionModel = entitySqlDaoWrapperFactory.become(SubscriptionSqlDao.class).getById(subscriptionId.toString(), context);
                 if (subscriptionModel == null) {
                     .error(String.format(..getFormat(), subscriptionId.toString()));
                     return null;
                 }
 
                 final UUID bundleId = subscriptionModel.getBundleId();
                 if (bundleId == null) {
                     .error(String.format(..getFormat(), subscriptionId.toString()));
                     return null;
                 }
 
                 final SubscriptionBundleModelDao bundleModel = entitySqlDaoWrapperFactory.become(BundleSqlDao.class).getById(bundleId.toString(), context);
                 if (bundleModel == null) {
                     .error(String.format(..getFormat(), bundleId.toString()));
                     return null;
                 }
                 return bundleModel.getAccountId();
             }
         });
     }
 
     @Override
     public SubscriptionBase getBaseSubscription(final UUID bundleIdfinal InternalTenantContext context) {
         return getBaseSubscription(bundleIdtruecontext);
     }
 
     @Override
     public SubscriptionBase getSubscriptionFromId(final UUID subscriptionIdfinal InternalTenantContext context) {
         final SubscriptionBase shellSubscription = .execute(new EntitySqlDaoTransactionWrapper<SubscriptionBase>() {
             @Override
             public SubscriptionBase inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final SubscriptionModelDao model = entitySqlDaoWrapperFactory.become(SubscriptionSqlDao.class).getById(subscriptionId.toString(), context);
                 return SubscriptionModelDao.toSubscription(model);
             }
         });
         return buildSubscription(shellSubscriptioncontext);
     }
 
     @Override
     public List<SubscriptionBasegetSubscriptions(final UUID bundleIdfinal InternalTenantContext context) {
         return buildBundleSubscriptions(getSubscriptionFromBundleId(bundleIdcontext), nullcontext);
     }
 
     private List<SubscriptionBasegetSubscriptionFromBundleId(final UUID bundleIdfinal InternalTenantContext context) {
             @Override
             public List<SubscriptionBaseinTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final List<SubscriptionModelDaomodels = entitySqlDaoWrapperFactory.become(SubscriptionSqlDao.class).getSubscriptionsFromBundleId(bundleId.toString(), context);
                 return new ArrayList<SubscriptionBase>(Collections2.transform(modelsnew Function<SubscriptionModelDaoSubscriptionBase>() {
                     @Override
                     public SubscriptionBase apply(@Nullable final SubscriptionModelDao input) {
                         return SubscriptionModelDao.toSubscription(input);
                     }
                 }));
             }
         });
     }
 
     @Override
         final Map<UUIDList<SubscriptionBase>> subscriptionsFromAccountId = getSubscriptionsFromAccountId(context);
 
         final List<SubscriptionBaseEventeventsForAccount = getEventsForAccountId(context);
 
         final Map<UUIDList<SubscriptionBase>> result = new HashMap<UUIDList<SubscriptionBase>>();
         for (final UUID bundleId : subscriptionsFromAccountId.keySet()) {
 
             final List<SubscriptionBasesubscriptionsForBundle = subscriptionsFromAccountId.get(bundleId);
             final Collection<UUIDsubscriptionIdsForBundle = Collections2.transform(subscriptionsForBundlenew Function<SubscriptionBaseUUID>() {
                 @Override
                 public UUID apply(final SubscriptionBase input) {
                     return input.getId();
                 }
             });
             final Multimap<UUIDSubscriptionBaseEventeventsForSubscriptions = ArrayListMultimap.create();
 
             for (final SubscriptionBase cur : subscriptionsForBundle) {
                 final Collection<SubscriptionBaseEventevents = Collections2.filter(eventsForAccountnew Predicate<SubscriptionBaseEvent>() {
                     @Override
                     public boolean apply(final SubscriptionBaseEvent input) {
                         return input.getSubscriptionId().equals(cur.getId());
 
                     }
                 });
                 eventsForSubscriptions.putAll(cur.getId(), ImmutableList.copyOf(events));
             }
 
             result.put(bundleIdbuildBundleSubscriptions(subscriptionsForBundleeventsForSubscriptionscontext));
         }
         return result;
     }
 
         final List<SubscriptionBaseallSubscriptions = .execute(new EntitySqlDaoTransactionWrapper<List<SubscriptionBase>>() {
             @Override
             public List<SubscriptionBaseinTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final List<SubscriptionModelDaomodels = entitySqlDaoWrapperFactory.become(SubscriptionSqlDao.class).getByAccountRecordId(context);
                 return new ArrayList<SubscriptionBase>(Collections2.transform(modelsnew Function<SubscriptionModelDaoSubscriptionBase>() {
                     @Override
                     public SubscriptionBase apply(final SubscriptionModelDao input) {
                         return SubscriptionModelDao.toSubscription(input);
                     }
                 }));
             }
         });
 
         final Map<UUIDList<SubscriptionBase>> result = new HashMap<UUIDList<SubscriptionBase>>();
         for (final SubscriptionBase subscriptionBase : allSubscriptions) {
             if (result.get(subscriptionBase.getBundleId()) == null) {
                 result.put(subscriptionBase.getBundleId(), new LinkedList<SubscriptionBase>());
             }
             result.get(subscriptionBase.getBundleId()).add(subscriptionBase);
         }
         return result;
     }
 
     @Override
     public void updateChargedThroughDate(final DefaultSubscriptionBase subscriptionfinal InternalCallContext context) {
         final Date ctd = (subscription.getChargedThroughDate() != null) ? subscription.getChargedThroughDate().toDate() : null;
 
             @Override
             public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final SubscriptionSqlDao transactionalDao = entitySqlDaoWrapperFactory.become(SubscriptionSqlDao.class);
                 transactionalDao.updateChargedThroughDate(subscription.getId().toString(), ctdcontext);
 
                 final BundleSqlDao bundleSqlDao = entitySqlDaoWrapperFactory.become(BundleSqlDao.class);
                 final String bundleId = subscription.getBundleId().toString();
                 bundleSqlDao.updateBundleLastSysTime(bundleId.getUTCNow().toDate(), context);
                 return null;
             }
         });
     }
 
     @Override
     public void createNextPhaseEvent(final DefaultSubscriptionBase subscriptionfinal SubscriptionBaseEvent nextPhasefinal InternalCallContext context) {
             @Override
             public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final SubscriptionEventSqlDao transactional = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class);
                 final UUID subscriptionId = subscription.getId();
                 cancelNextPhaseEventFromTransaction(subscriptionIdentitySqlDaoWrapperFactorycontext);
                 transactional.create(new SubscriptionEventModelDao(nextPhase), context);
                 recordFutureNotificationFromTransaction(entitySqlDaoWrapperFactory,
                                                         nextPhase.getEffectiveDate(),
                                                         new SubscriptionNotificationKey(nextPhase.getId()), context);
 
                 // Notify the Bus of the requested change
                 notifyBusOfRequestedChange(entitySqlDaoWrapperFactorysubscriptionnextPhasecontext);
 
                 return null;
             }
         });
     }
 
     @Override
     public SubscriptionBaseEvent getEventById(final UUID eventIdfinal InternalTenantContext context) {
             @Override
             public SubscriptionBaseEvent inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 SubscriptionEventModelDao model = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class).getById(eventId.toString(), context);
                 return SubscriptionEventModelDao.toSubscriptionEvent(model);
             }
         });
     }
 
     @Override
     public List<SubscriptionBaseEventgetEventsForSubscription(final UUID subscriptionIdfinal InternalTenantContext context) {
             @Override
             public List<SubscriptionBaseEventinTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final List<SubscriptionEventModelDaomodels = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class).getEventsForSubscription(subscriptionId.toString(), context);
                 return filterSubscriptionBaseEvents(models);
             }
         });
     }
 
     @Override
     public Map<UUIDList<SubscriptionBaseEvent>> getEventsForBundle(final UUID bundleIdfinal InternalTenantContext context) {
             @Override
             public Map<UUIDList<SubscriptionBaseEvent>> inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final SubscriptionSqlDao transactional = entitySqlDaoWrapperFactory.become(SubscriptionSqlDao.class);
 
                 final List<SubscriptionModelDaosubscriptionModels = transactional.getSubscriptionsFromBundleId(bundleId.toString(), context);
                 if (subscriptionModels.size() == 0) {
                     return Collections.emptyMap();
                 }
 
                 final SubscriptionEventSqlDao eventsDaoFromSameTransaction = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class);
                 final Map<UUIDList<SubscriptionBaseEvent>> result = new HashMap<UUIDList<SubscriptionBaseEvent>>();
                 for (final SubscriptionModelDao cur : subscriptionModels) {
                     final List<SubscriptionEventModelDaoeventModels = eventsDaoFromSameTransaction.getEventsForSubscription(cur.getId().toString(), context);
                     final List<SubscriptionBaseEventevents = new ArrayList<SubscriptionBaseEvent>(Collections2.transform(eventModelsnew Function<SubscriptionEventModelDaoSubscriptionBaseEvent>() {
                         @Override
                         public SubscriptionBaseEvent apply(@Nullable final SubscriptionEventModelDao input) {
                             return SubscriptionEventModelDao.toSubscriptionEvent(input);
                         }
                     }));
                     result.put(cur.getId(), events);
                 }
                 return result;
             }
         });
     }
 
     @Override
     public List<SubscriptionBaseEventgetPendingEventsForSubscription(final UUID subscriptionIdfinal InternalTenantContext context) {
         final Date now = .getUTCNow().toDate();
 
             @Override
             public List<SubscriptionBaseEventinTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final List<SubscriptionEventModelDaoeventModels = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class).getFutureActiveEventForSubscription(subscriptionId.toString(), nowcontext);
                 final List<SubscriptionBaseEventevents = new ArrayList<SubscriptionBaseEvent>(Collections2.transform(eventModelsnew Function<SubscriptionEventModelDaoSubscriptionBaseEvent>() {
                     @Override
                     public SubscriptionBaseEvent apply(@Nullable final SubscriptionEventModelDao input) {
                         return SubscriptionEventModelDao.toSubscriptionEvent(input);
                     }
                 }));
                 return events;
             }
         });
     }
 
     @Override
     public void createSubscription(final DefaultSubscriptionBase subscriptionfinal List<SubscriptionBaseEventinitialEventsfinal InternalCallContext context) {
             @Override
             public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final SubscriptionSqlDao transactional = entitySqlDaoWrapperFactory.become(SubscriptionSqlDao.class);
                 transactional.create(new SubscriptionModelDao(subscription), context);
 
                 final SubscriptionEventSqlDao eventsDaoFromSameTransaction = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class);
                 for (final SubscriptionBaseEvent cur : initialEvents) {
                     eventsDaoFromSameTransaction.create(new SubscriptionEventModelDao(cur), context);
 
                     final boolean isBusEvent = cur.getEffectiveDate().compareTo(.getUTCNow()) <= 0 && (cur.getType() == .);
                     recordBusOrFutureNotificationFromTransaction(subscriptioncurentitySqlDaoWrapperFactoryisBusEvent, 0, context);
 
                 }
                 // Notify the Bus of the latest requested change, if needed
                 if (initialEvents.size() > 0) {
                     notifyBusOfRequestedChange(entitySqlDaoWrapperFactorysubscriptioninitialEvents.get(initialEvents.size() - 1), context);
                 }
                 return null;
             }
         });
     }
 
     @Override
     public void recreateSubscription(final DefaultSubscriptionBase subscriptionfinal List<SubscriptionBaseEventrecreateEventsfinal InternalCallContext context) {
             @Override
             public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final SubscriptionEventSqlDao transactional = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class);
 
                 for (final SubscriptionBaseEvent cur : recreateEvents) {
                     transactional.create(new SubscriptionEventModelDao(cur), context);
 
                     final boolean isBusEvent = cur.getEffectiveDate().compareTo(.getUTCNow()) <= 0 && (cur.getType() == .);
                     recordBusOrFutureNotificationFromTransaction(subscriptioncurentitySqlDaoWrapperFactoryisBusEvent, 0, context);
                 }
 
                 // Notify the Bus of the latest requested change
                 notifyBusOfRequestedChange(entitySqlDaoWrapperFactorysubscriptionrecreateEvents.get(recreateEvents.size() - 1), context);
 
                 return null;
             }
         });
     }
 
     @Override
     public void cancelSubscriptions(final List<DefaultSubscriptionBasesubscriptionsfinal List<SubscriptionBaseEventcancelEventsfinal InternalCallContext context) {
 
             @Override
             public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 for (int i = 0; i < subscriptions.size(); i++) {
                     final DefaultSubscriptionBase subscription = subscriptions.get(i);
                     final SubscriptionBaseEvent cancelEvent = cancelEvents.get(i);
                     cancelSubscriptionFromTransaction(subscriptioncancelEvententitySqlDaoWrapperFactorycontexti);
                 }
                 return null;
             }
         });
     }
 
     @Override
     public void cancelSubscription(final DefaultSubscriptionBase subscriptionfinal SubscriptionBaseEvent cancelEventfinal InternalCallContext contextfinal int seqId) {
             @Override
             public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 cancelSubscriptionFromTransaction(subscriptioncancelEvententitySqlDaoWrapperFactorycontextseqId);
                 return null;
             }
         });
     }
 
     @Override
     public void uncancelSubscription(final DefaultSubscriptionBase subscriptionfinal List<SubscriptionBaseEventuncancelEventsfinal InternalCallContext context) {
             @Override
             public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final SubscriptionEventSqlDao transactional = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class);
 
                 final UUID subscriptionId = subscription.getId();
                 SubscriptionEventModelDao cancelledEvent = null;
                 final Date now = .getUTCNow().toDate();
                 final List<SubscriptionEventModelDaoeventModels = transactional.getFutureActiveEventForSubscription(subscriptionId.toString(), nowcontext);
 
                 for (final SubscriptionEventModelDao cur : eventModels) {
                     if (cur.getUserType() == .) {
                         if (cancelledEvent != null) {
                             throw new SubscriptionBaseError(String.format("Found multiple cancelWithRequestedDate active events for subscriptions %s"subscriptionId.toString()));
                         }
                         cancelledEvent = cur;
                     }
                 }
 
                 if (cancelledEvent != null) {
                     final String cancelledEventId = cancelledEvent.getId().toString();
                     transactional.unactiveEvent(cancelledEventIdcontext);
                     for (final SubscriptionBaseEvent cur : uncancelEvents) {
                         transactional.create(new SubscriptionEventModelDao(cur), context);
                         recordFutureNotificationFromTransaction(entitySqlDaoWrapperFactory,
                                                                 cur.getEffectiveDate(),
                                                                 new SubscriptionNotificationKey(cur.getId()),
                                                                 context);
                     }
 
                     // Notify the Bus of the latest requested change
                     notifyBusOfRequestedChange(entitySqlDaoWrapperFactorysubscriptionuncancelEvents.get(uncancelEvents.size() - 1), context);
                 }
 
                 return null;
             }
         });
     }
 
     @Override
     public void changePlan(final DefaultSubscriptionBase subscriptionfinal List<SubscriptionBaseEventchangeEventsfinal InternalCallContext context) {
             @Override
             public Void inTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
 
                 final SubscriptionEventSqlDao transactional = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class);
                 final UUID subscriptionId = subscription.getId();
 
                 final List<SubscriptionBaseEventchangeEventsTweakedWithMigrateBilling = reinsertFutureMigrateBillingEventOnChangeFromTransaction(subscriptionId,
                                                                                                                                                    changeEvents,
                                                                                                                                                    entitySqlDaoWrapperFactory,
                                                                                                                                                    context);
 
                 cancelFutureEventsFromTransaction(subscriptionIdentitySqlDaoWrapperFactorycontext);
 
                 for (final SubscriptionBaseEvent cur : changeEventsTweakedWithMigrateBilling) {
 
                     transactional.create(new SubscriptionEventModelDao(cur), context);
 
                     final boolean isBusEvent = cur.getEffectiveDate().compareTo(.getUTCNow()) <= 0 && (cur.getType() == .);
                     recordBusOrFutureNotificationFromTransaction(subscriptioncurentitySqlDaoWrapperFactoryisBusEvent, 0, context);
                 }
 
                 // Notify the Bus of the latest requested change
                 final SubscriptionBaseEvent finalEvent = changeEventsTweakedWithMigrateBilling.get(changeEvents.size() - 1);
                 notifyBusOfRequestedChange(entitySqlDaoWrapperFactorysubscriptionfinalEventcontext);
 
                 return null;
             }
         });
     }
 
     //
     // This piece of code has been isolated in its own method in order to allow for migrated subscriptions to have their plan to changed prior
     // to MIGRATE_BILLING; the effect will be to reflect the change from an subscription point of view while ignoring the change until we hit
     // the begining of the billing, that is when we hit the MIGRATE_BILLING event. If we had a clear separation between subscription and
     // billing that would not be needed.
     //
     // If there is a change of plan prior to a future MIGRATE_BILLING, we want to modify the existing MIGRATE_BILLING so it reflects
     // the new plan, phase, pricelist; Invoice will only see the MIGRATE_BILLING as things prior to that will be ignored, so we need to make sure
     // that event reflects the correct subscription information.
     //
     //
     final List<SubscriptionBaseEventreinsertFutureMigrateBillingEventOnChangeFromTransaction(final UUID subscriptionIdfinal List<SubscriptionBaseEventchangeEventsfinal EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactoryfinal InternalCallContext context) {
         final SubscriptionEventModelDao migrateBillingEvent = findFutureEventFromTransaction(subscriptionIdentitySqlDaoWrapperFactory..context);
         if (migrateBillingEvent == null) {
             // No future migrate billing : returns same list
             return changeEvents;
         }
 
         String prevPlan = null;
         String prevPhase = null;
         String prevPriceList = null;
         String curPlan = null;
         String curPhase = null;
         String curPriceList = null;
         for (SubscriptionBaseEvent cur : changeEvents) {
             switch (cur.getType()) {
                 case :
                     final ApiEvent apiEvent = (ApiEventcur;
                     curPlan = apiEvent.getEventPlan();
                     curPhase = apiEvent.getEventPlanPhase();
                     curPriceList = apiEvent.getPriceList();
                     break;
 
                 case :
                     final PhaseEvent phaseEvent = (PhaseEventcur;
                     curPhase = phaseEvent.getPhase();
                     break;
 
                 default:
                     throw new SubscriptionBaseError("Unknown event type " + cur.getType());
             }
 
             if (cur.getEffectiveDate().compareTo(migrateBillingEvent.getEffectiveDate()) > 0) {
                 if (cur.getType() == . && ((ApiEventcur).getEventType() == .) {
                     // This is an EOT change that is occurring after the MigrateBilling : returns same list
                     return changeEvents;
                 }
                 // We found the first event after the migrate billing
                 break;
             }
             prevPlan = curPlan;
             prevPhase = curPhase;
             prevPriceList = curPriceList;
         }
 
         if (prevPlan != null) {
             // Create the new MIGRATE_BILLING with same effectiveDate but new plan information
             final DateTime now = .getUTCNow();
             final ApiEventBuilder builder = new ApiEventBuilder()
                     .setActive(true)
                     .setEventType(.)
                     .setFromDisk(true)
                     .setTotalOrdering(migrateBillingEvent.getTotalOrdering())
                     .setUuid(UUID.randomUUID())
                     .setSubscriptionId(migrateBillingEvent.getSubscriptionId())
                     .setCreatedDate(now)
                     .setUpdatedDate(now)
                     .setRequestedDate(migrateBillingEvent.getRequestedDate())
                     .setEffectiveDate(migrateBillingEvent.getEffectiveDate())
                     .setProcessedDate(now)
                     .setActiveVersion(migrateBillingEvent.getCurrentVersion())
                     .setEventPlan(prevPlan)
                     .setEventPlanPhase(prevPhase)
                     .setEventPriceList(prevPriceList);
 
             final SubscriptionBaseEvent newMigrateBillingEvent = new ApiEventMigrateBilling(builder);
             changeEvents.add(newMigrateBillingEvent);
 
             Collections.sort(changeEventsnew Comparator<SubscriptionBaseEvent>() {
                 @Override
                 public int compare(final SubscriptionBaseEvent o1final SubscriptionBaseEvent o2) {
                     return o1.getEffectiveDate().compareTo(o2.getEffectiveDate());
                 }
             });
         }
 
         return changeEvents;
     }
 
         final Collection<SubscriptionEventModelDaofilteredModels = Collections2.filter(modelsnew Predicate<SubscriptionEventModelDao>() {
             @Override
             public boolean apply(@Nullable final SubscriptionEventModelDao input) {
                 return input.getUserType() != .;
             }
         });
         return new ArrayList<SubscriptionBaseEvent>(Collections2.transform(filteredModelsnew Function<SubscriptionEventModelDaoSubscriptionBaseEvent>() {
             @Override
             public SubscriptionBaseEvent apply(@Nullable final SubscriptionEventModelDao input) {
                 return SubscriptionEventModelDao.toSubscriptionEvent(input);
             }
         }));
     }
 
             @Override
             public List<SubscriptionBaseEventinTransaction(final EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactorythrows Exception {
                 final List<SubscriptionEventModelDaomodels = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class).getByAccountRecordId(context);
                 return filterSubscriptionBaseEvents(models);
             }
         });
     }
 
     private void cancelSubscriptionFromTransaction(final DefaultSubscriptionBase subscriptionfinal SubscriptionBaseEvent cancelEventfinal EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactoryfinal InternalCallContext contextfinal int seqId)
             throws EntityPersistenceException {
         final UUID subscriptionId = subscription.getId();
         cancelFutureEventsFromTransaction(subscriptionIdentitySqlDaoWrapperFactorycontext);
         entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class).create(new SubscriptionEventModelDao(cancelEvent), context);
 
         final boolean isBusEvent = cancelEvent.getEffectiveDate().compareTo(.getUTCNow()) <= 0;
         recordBusOrFutureNotificationFromTransaction(subscriptioncancelEvententitySqlDaoWrapperFactoryisBusEventseqIdcontext);
 
         // Notify the Bus of the requested change
         notifyBusOfRequestedChange(entitySqlDaoWrapperFactorysubscriptioncancelEventcontext);
     }
 
     private void cancelNextPhaseEventFromTransaction(final UUID subscriptionIdfinal EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactoryfinal InternalCallContext context) {
         cancelFutureEventFromTransaction(subscriptionIdentitySqlDaoWrapperFactory.nullcontext);
     }
 
     private void cancelFutureEventsFromTransaction(final UUID subscriptionIdfinal EntitySqlDaoWrapperFactory<EntitySqlDaoentitySqlDaoWrapperFactoryfinal InternalCallContext context) {
         final Date now = .getUTCNow().toDate();
         final List<SubscriptionEventModelDaoeventModels = entitySqlDaoWrapperFactory.become(SubscriptionEventSqlDao.class).getFutureActiveEventForSubscription(subscriptionId.toString(), nowcontext);
         for (final SubscriptionEventModelDao cur : eventModels) {
             unactivateEventFromTransaction(curentitySqlDaoWrapperFactorycontext);
         }
     }
 
     private void cancelFutureEventFromTransaction(final UUID subscriptionIdfinal EntitySqlDaoWrapperFactory<EntitySqlDaodaofinal EventType type,
                                                   @Nullable final ApiEventType apiTypefinal InternalCallContext context) {
         final SubscriptionEventModelDao futureEvent = findFutureEventFromTransaction(subscriptionIddaotypeapiTypecontext);
         unactivateEventFromTransaction(futureEventdaocontext);
     }
 
     private SubscriptionEventModelDao findFutureEventFromTransaction(final UUID subscriptionIdfinal EntitySqlDaoWrapperFactory<EntitySqlDaodaofinal EventType type,
                                                                      @Nullable final ApiEventType apiTypefinal InternalCallContext context) {
 
         SubscriptionEventModelDao futureEvent = null;
         final Date now = .getUTCNow().toDate();
         final List<SubscriptionEventModelDaoeventModels = dao.become(SubscriptionEventSqlDao.class).getFutureActiveEventForSubscription(subscriptionId.toString(), nowcontext);
         for (final SubscriptionEventModelDao cur : eventModels) {
             if (cur.getEventType() == type &&
                 (apiType == null || apiType == cur.getUserType())) {
                 if (futureEvent != null) {
                     throw new SubscriptionBaseError(String.format("Found multiple future events for type %s for subscriptions %s",
                                                                   typesubscriptionId.toString()));
                 }
                 futureEvent = cur;
                 // To check that there is only one such event
                 //break;
             }
         }
         return futureEvent;
     }
 
     private void unactivateEventFromTransaction(final SubscriptionEventModelDao eventfinal EntitySqlDaoWrapperFactory<EntitySqlDaodaofinal InternalCallContext context) {
         if (event != null) {
             final String eventId = event.getId().toString();
             dao.become(SubscriptionEventSqlDao.class).unactiveEvent(eventIdcontext);
         }
     }
 
     private SubscriptionBase buildSubscription(final SubscriptionBase inputfinal InternalTenantContext context) {
 
         if (input == null) {
             return null;
         }
         final List<SubscriptionBasebundleInput = new ArrayList<SubscriptionBase>();
         if (input.getCategory() == .) {
             final SubscriptionBase baseSubscription = getBaseSubscription(input.getBundleId(), falsecontext);
             if (baseSubscription == null) {
                 return null;
             }
 
             bundleInput.add(baseSubscription);
             bundleInput.add(input);
         } else {
             bundleInput.add(input);
         }
 
         final List<SubscriptionBasereloadedSubscriptions = buildBundleSubscriptions(bundleInputnullcontext);
         for (final SubscriptionBase cur : reloadedSubscriptions) {
             if (cur.getId().equals(input.getId())) {
                 return cur;
             }
         }
 
         throw new SubscriptionBaseError("Unexpected code path in buildSubscription");
     }
 
     private List<SubscriptionBase