@Transactional
void removeEntitlement(Entitlement entitlement,
boolean regenModified) {
Consumer consumer = entitlement.getConsumer();
Pool pool = entitlement.getPool();
// Similarly to when we add an entitlement, lock the pool when we remove one, too.
// This won't do anything for over/under consumption, but it will prevent
// concurrency issues if someone else is operating on the pool.
pool = poolCurator.lockAndLoad(pool);
consumer.removeEntitlement(entitlement);
// Look for pools referencing this entitlement as their source
// entitlement and clean them up as well
// we need to create a list of pools and entitlements to delete,
// otherwise we are tampering with the loop iterator from inside
// the loop (#811581)
Set<Pool> deletablePools = new HashSet<Pool>();
for (Pool p : poolCurator.listBySourceEntitlement(entitlement)) {
for (Entitlement e : p.getEntitlements()) {
this.revokeEntitlement(e);
}
deletablePools.add(p);
}
for (Pool dp : deletablePools) {
deletePool(dp);
}
pool.getEntitlements().remove(entitlement);
poolCurator.merge(pool);
entitlementCurator.delete(entitlement);
Event event = eventFactory.entitlementDeleted(entitlement);
// The quantity is calculated at fetch time. We update it here
// To reflect what we just removed from the db.
pool.setConsumed(pool.getConsumed() - entitlement.getQuantity());
if (consumer.getType().isManifest()) {
pool.setExported(pool.getExported() - entitlement.getQuantity());
}
// Check for a single stacked sub pool as well. We'll need to either
// update or delete the sub pool now that all other pools have been deleted.
if (!"true".equals(pool.getAttributeValue("pool_derived")) &&
pool.hasProductAttribute("stacking_id")) {
String stackId = pool.getProductAttributeValue("stacking_id");
Pool stackedSubPool = poolCurator.getSubPoolForStackId(consumer, stackId);
if (stackedSubPool != null) {
List<Entitlement> stackedEnts =
this.entitlementCurator.findByStackId(consumer, stackId);
// If there are no stacked entitlements, we need to delete the