use of org.killbill.billing.entitlement.api.BlockingState in project killbill by killbill.
the class DefaultBlockingStateDao method getBlockedStatus.
private BlockingAggregator getBlockedStatus(final BlockingStateSqlDao sqlDao, final Handle handle, final UUID blockableId, final BlockingStateType type, @Nullable final UUID bundleId, final DateTime upToDate, final InternalTenantContext context) throws BlockingApiException {
final List<BlockingState> accountBlockingStates;
final List<BlockingState> bundleBlockingStates;
final List<BlockingState> subscriptionBlockingStates;
if (type == BlockingStateType.SUBSCRIPTION) {
final UUID accountId = nonEntityDao.retrieveIdFromObjectInTransaction(context.getAccountRecordId(), ObjectType.ACCOUNT, cacheControllerDispatcher.getCacheController(CacheType.OBJECT_ID), handle);
accountBlockingStates = getBlockingState(sqlDao, accountId, BlockingStateType.ACCOUNT, upToDate, context);
bundleBlockingStates = getBlockingState(sqlDao, bundleId, BlockingStateType.SUBSCRIPTION_BUNDLE, upToDate, context);
subscriptionBlockingStates = getBlockingState(sqlDao, blockableId, BlockingStateType.SUBSCRIPTION, upToDate, context);
} else if (type == BlockingStateType.SUBSCRIPTION_BUNDLE) {
final UUID accountId = nonEntityDao.retrieveIdFromObjectInTransaction(context.getAccountRecordId(), ObjectType.ACCOUNT, cacheControllerDispatcher.getCacheController(CacheType.OBJECT_ID), handle);
accountBlockingStates = getBlockingState(sqlDao, accountId, BlockingStateType.ACCOUNT, upToDate, context);
bundleBlockingStates = getBlockingState(sqlDao, blockableId, BlockingStateType.SUBSCRIPTION_BUNDLE, upToDate, context);
subscriptionBlockingStates = ImmutableList.<BlockingState>of();
} else {
// BlockingStateType.ACCOUNT {
accountBlockingStates = getBlockingState(sqlDao, blockableId, BlockingStateType.ACCOUNT, upToDate, context);
bundleBlockingStates = ImmutableList.<BlockingState>of();
subscriptionBlockingStates = ImmutableList.<BlockingState>of();
}
return statelessBlockingChecker.getBlockedState(accountBlockingStates, bundleBlockingStates, subscriptionBlockingStates);
}
use of org.killbill.billing.entitlement.api.BlockingState in project killbill by killbill.
the class ProxyBlockingStateDao method insertTiedBlockingStatesInTheRightOrder.
private static BlockingState insertTiedBlockingStatesInTheRightOrder(final Collection<BlockingState> result, final BlockingState current, final BlockingState next, final boolean prevBlocked, final boolean currentBlocked, final boolean nextBlocked) {
final BlockingState prev;
if (prevBlocked && currentBlocked && nextBlocked) {
// Tricky use case, bail
return null;
} else if (prevBlocked && currentBlocked && !nextBlocked) {
result.add(next);
result.add(current);
prev = current;
} else if (prevBlocked && !currentBlocked && nextBlocked) {
result.add(current);
result.add(next);
prev = next;
} else if (prevBlocked && !currentBlocked && !nextBlocked) {
// Tricky use case, bail
return null;
} else if (!prevBlocked && currentBlocked && nextBlocked) {
// Tricky use case, bail
return null;
} else if (!prevBlocked && currentBlocked && !nextBlocked) {
result.add(current);
result.add(next);
prev = next;
} else if (!prevBlocked && !currentBlocked && nextBlocked) {
result.add(next);
result.add(current);
prev = current;
} else if (!prevBlocked && !currentBlocked && !nextBlocked) {
// Tricky use case, bail
return null;
} else {
throw new ShouldntHappenException("Marker exception for code clarity");
}
return prev;
}
use of org.killbill.billing.entitlement.api.BlockingState in project killbill by killbill.
the class EntitlementUtils method setBlockingStatesAndPostBlockingTransitionEvent.
public void setBlockingStatesAndPostBlockingTransitionEvent(final Iterable<BlockingState> blockingStates, @Nullable final UUID bundleId, final InternalCallContext internalCallContext) {
final ImmutableMap.Builder<BlockingState, Optional<UUID>> states = new ImmutableMap.Builder<BlockingState, Optional<UUID>>();
final Optional<UUID> bundleIdOptional = Optional.<UUID>fromNullable(bundleId);
for (final BlockingState blockingState : blockingStates) {
states.put(blockingState, bundleIdOptional);
}
dao.setBlockingStatesAndPostBlockingTransitionEvent(states.build(), internalCallContext);
}
use of org.killbill.billing.entitlement.api.BlockingState in project killbill by killbill.
the class EventsStreamBuilder method buildForAccount.
// Special signature for ProxyBlockingStateDao to save a DAO call
public AccountEventsStreams buildForAccount(final Map<UUID, List<SubscriptionBase>> subscriptions, final InternalTenantContext internalTenantContext) throws EntitlementApiException {
// Retrieve the account
final ImmutableAccountData account;
try {
account = accountInternalApi.getImmutableAccountDataByRecordId(internalTenantContext.getAccountRecordId(), internalTenantContext);
} catch (AccountApiException e) {
throw new EntitlementApiException(e);
}
if (subscriptions.isEmpty()) {
// Bail early
return new DefaultAccountEventsStreams(account);
}
// Retrieve the bundles
final List<SubscriptionBaseBundle> bundles = subscriptionInternalApi.getBundlesForAccount(account.getId(), internalTenantContext);
// Map bundle id -> bundles
final Map<UUID, SubscriptionBaseBundle> bundlesPerId = new HashMap<UUID, SubscriptionBaseBundle>();
for (final SubscriptionBaseBundle bundle : bundles) {
bundlesPerId.put(bundle.getId(), bundle);
}
// Retrieve the blocking states
final List<BlockingState> blockingStatesForAccount = defaultBlockingStateDao.getBlockingAllForAccountRecordId(internalTenantContext);
// Optimization: build lookup tables for blocking states states
final Collection<BlockingState> accountBlockingStates = new LinkedList<BlockingState>();
final Map<UUID, List<BlockingState>> blockingStatesPerSubscription = new HashMap<UUID, List<BlockingState>>();
final Map<UUID, List<BlockingState>> blockingStatesPerBundle = new HashMap<UUID, List<BlockingState>>();
for (final BlockingState blockingState : blockingStatesForAccount) {
if (BlockingStateType.SUBSCRIPTION.equals(blockingState.getType())) {
if (blockingStatesPerSubscription.get(blockingState.getBlockedId()) == null) {
blockingStatesPerSubscription.put(blockingState.getBlockedId(), new LinkedList<BlockingState>());
}
blockingStatesPerSubscription.get(blockingState.getBlockedId()).add(blockingState);
} else if (BlockingStateType.SUBSCRIPTION_BUNDLE.equals(blockingState.getType())) {
if (blockingStatesPerBundle.get(blockingState.getBlockedId()) == null) {
blockingStatesPerBundle.put(blockingState.getBlockedId(), new LinkedList<BlockingState>());
}
blockingStatesPerBundle.get(blockingState.getBlockedId()).add(blockingState);
} else if (BlockingStateType.ACCOUNT.equals(blockingState.getType()) && account.getId().equals(blockingState.getBlockedId())) {
accountBlockingStates.add(blockingState);
}
}
// Build the EventsStream objects
final Map<UUID, Integer> bcdCache = new HashMap<UUID, Integer>();
final Map<UUID, Collection<EventsStream>> entitlementsPerBundle = new HashMap<UUID, Collection<EventsStream>>();
for (final UUID bundleId : subscriptions.keySet()) {
final SubscriptionBaseBundle bundle = bundlesPerId.get(bundleId);
final List<SubscriptionBase> allSubscriptionsForBundle = subscriptions.get(bundleId);
final SubscriptionBase baseSubscription = findBaseSubscription(allSubscriptionsForBundle);
final List<BlockingState> bundleBlockingStates = MoreObjects.firstNonNull(blockingStatesPerBundle.get(bundleId), ImmutableList.<BlockingState>of());
if (entitlementsPerBundle.get(bundleId) == null) {
entitlementsPerBundle.put(bundleId, new LinkedList<EventsStream>());
}
for (final SubscriptionBase subscription : allSubscriptionsForBundle) {
final List<BlockingState> subscriptionBlockingStatesOnDisk = MoreObjects.firstNonNull(blockingStatesPerSubscription.get(subscription.getId()), ImmutableList.<BlockingState>of());
// We cannot always use blockingStatesForAccount here: we need subscriptionBlockingStates to contain the events not on disk when building an EventsStream
// for an add-on - which means going through the magic of ProxyBlockingStateDao, which will recursively
// create EventsStream objects. To avoid an infinite recursion, bypass ProxyBlockingStateDao when it's not
// needed, i.e. if this EventStream is for a standalone or a base subscription
final List<BlockingState> subscriptionBlockingStates;
if (baseSubscription == null || subscription.getId().equals(baseSubscription.getId())) {
subscriptionBlockingStates = subscriptionBlockingStatesOnDisk;
} else {
subscriptionBlockingStates = blockingStateDao.getBlockingHistory(subscriptionBlockingStatesOnDisk, blockingStatesForAccount, account, bundle, baseSubscription, subscription, allSubscriptionsForBundle, internalTenantContext);
}
// Merge the BlockingStates
final Collection<BlockingState> blockingStateSet = new LinkedHashSet<BlockingState>(accountBlockingStates);
blockingStateSet.addAll(bundleBlockingStates);
blockingStateSet.addAll(subscriptionBlockingStates);
final List<BlockingState> blockingStates = ProxyBlockingStateDao.sortedCopy(blockingStateSet);
final EventsStream eventStream = buildForEntitlement(account, bundle, baseSubscription, subscription, allSubscriptionsForBundle, blockingStates, bcdCache, internalTenantContext);
entitlementsPerBundle.get(bundleId).add(eventStream);
}
}
return new DefaultAccountEventsStreams(account, bundles, entitlementsPerBundle);
}
use of org.killbill.billing.entitlement.api.BlockingState in project killbill by killbill.
the class DefaultEntitlementService method blockAddOnsIfRequired.
private void blockAddOnsIfRequired(final EntitlementNotificationKey key, final DefaultEntitlement entitlement, final TenantContext callContext, final InternalCallContext internalCallContext) throws EntitlementApiException {
final Collection<NotificationEvent> notificationEvents = new ArrayList<NotificationEvent>();
final Collection<BlockingState> blockingStates = entitlement.computeAddOnBlockingStates(key.getEffectiveDate(), notificationEvents, callContext, internalCallContext);
// Record the new state first, then insert the notifications to avoid race conditions
entitlementUtils.setBlockingStatesAndPostBlockingTransitionEvent(blockingStates, entitlement.getBundleId(), internalCallContext);
for (final NotificationEvent notificationEvent : notificationEvents) {
recordFutureNotification(key.getEffectiveDate(), notificationEvent, internalCallContext);
}
}
Aggregations