use of org.candlepin.model.dto.Subscription in project candlepin by candlepin.
the class SubscriptionReconciler method reconcile.
/**
* Reconciles incoming entitlements to existing pools to attempt to limit
* the number of pools we must destroy and revoke.
*
* Each set is mapped against the upstream pool ID. Subscriptions originating from
* different pools will never match each other for replacement.
*
* First match attempts a direct match of entitlement ID from incoming
* entitlements for comparison to existing pools. If so we re-use the existing pool.
* (note that despite the same entitlement ID, quantity and other data may have
* changed)
*
* Next we attempt to match on exact quantity. This would allow the user to re-create
* a distributor upstream and re-assign it the same entitlement quantities from the
* same pools, without triggering a mass regen on import.
*
* The last attempt will order the remaining incoming entitlements by quantity, and
* match these against a quantity ordered list of the remaining pools for that
* upstream pool.
*
* Remaining incoming subscriptions that did not match any pools per the above are
* treated as new subscriptions.
*
* @param owner
* The owner for which the subscriptions are being imported
*
* @param subsToImport
* A collection of subscriptions which are being imported
*
* @return
* The collection of reconciled subscriptions
*/
public Collection<Subscription> reconcile(Owner owner, Collection<Subscription> subsToImport) {
Map<String, Map<String, Pool>> existingPoolsByUpstreamPool = this.mapPoolsByUpstreamPool(owner);
// if we can match to the entitlement id do it.
// we need a new list to hold the ones that are left
Set<Subscription> subscriptionsStillToImport = new HashSet<>();
for (Subscription subscription : subsToImport) {
Pool local = null;
Map<String, Pool> map = existingPoolsByUpstreamPool.get(subscription.getUpstreamPoolId());
if (map == null || map.isEmpty()) {
log.info("New subscription for incoming entitlement ID: {}", subscription.getUpstreamEntitlementId());
continue;
}
local = map.get(subscription.getUpstreamEntitlementId());
if (local != null) {
mergeSubscription(subscription, local, map);
log.info("Merging subscription for incoming entitlement id [{}] into subscription with " + "existing entitlement id [{}]. Entitlement id match.", subscription.getUpstreamEntitlementId(), local.getUpstreamEntitlementId());
} else {
subscriptionsStillToImport.add(subscription);
log.warn("Subscription for incoming entitlement id [{}] does not have an entitlement id " + "match in the current subscriptions for the upstream pool id [{}]", subscription.getUpstreamEntitlementId(), subscription.getUpstreamPoolId());
}
}
// matches will be made against the upstream pool id and quantity.
// we need a new list to hold the ones that are left
List<Subscription> subscriptionsNeedQuantityMatch = new ArrayList<>();
for (Subscription subscription : subscriptionsStillToImport) {
Pool local = null;
Map<String, Pool> map = existingPoolsByUpstreamPool.get(subscription.getUpstreamPoolId());
if (map == null) {
map = new HashMap<>();
}
for (Pool localSub : map.values()) {
// TODO quantity
long quantity = localSub.getQuantity() != null ? localSub.getQuantity() : 1;
long multiplier = localSub.getProduct().getMultiplier() != null ? localSub.getProduct().getMultiplier() : 1;
Long effectiveQuantity = Long.valueOf(quantity / multiplier);
if (effectiveQuantity.equals(subscription.getQuantity())) {
local = localSub;
break;
}
}
if (local != null) {
mergeSubscription(subscription, local, map);
log.info("Merging subscription for incoming entitlement id [{}] into subscription with " + "existing entitlement id [{}]. Exact quantity match.", subscription.getUpstreamEntitlementId(), local.getUpstreamEntitlementId());
} else {
subscriptionsNeedQuantityMatch.add(subscription);
log.warn("Subscription for incoming entitlement id [{}] does not have an exact quantity " + "match in the current subscriptions for the upstream pool id [{}]", subscription.getUpstreamEntitlementId(), subscription.getUpstreamPoolId());
}
}
// matches will be made against the upstream pool id and quantity.
// quantities will just match by position from highest to lowest
// we need a new list to hold the ones that are left
Subscription[] inNeed = subscriptionsNeedQuantityMatch.toArray(new Subscription[0]);
Arrays.sort(inNeed, new SubQuantityComparator());
for (Subscription subscription : inNeed) {
Pool local = null;
Map<String, Pool> map = existingPoolsByUpstreamPool.get(subscription.getUpstreamPoolId());
if (map == null || map.isEmpty()) {
log.info("Creating new subscription for incoming entitlement with id [{}]", subscription.getUpstreamEntitlementId());
continue;
}
Pool[] locals = map.values().toArray(new Pool[0]);
Arrays.sort(locals, new QuantityComparator());
local = locals[0];
mergeSubscription(subscription, local, map);
log.info("Merging subscription for incoming entitlement id [{}] into subscription with " + "existing entitlement id [{}] Ordered quantity match.", subscription.getUpstreamEntitlementId(), local.getUpstreamEntitlementId());
}
return subsToImport;
}
use of org.candlepin.model.dto.Subscription in project candlepin by candlepin.
the class HostedTestSubscriptionServiceAdapter method deleteSubscription.
public boolean deleteSubscription(String id) {
if (idMap.containsKey(id)) {
Subscription s = idMap.remove(id);
ownerMap.get(s.getOwner().getKey()).remove(s);
productMap.get(s.getProduct().getId()).remove(s);
return true;
}
return false;
}
use of org.candlepin.model.dto.Subscription in project candlepin by candlepin.
the class HostedTestSubscriptionServiceAdapter method updateSubscription.
public Subscription updateSubscription(Subscription ss) {
deleteSubscription(ss.getId());
Subscription s = createSubscription(ss);
return s;
}
use of org.candlepin.model.dto.Subscription in project candlepin by candlepin.
the class PoolCuratorTest method confirmBonusPoolDeleted.
@Test
public void confirmBonusPoolDeleted() {
Subscription sub = TestUtil.createSubscription(owner, product, new HashSet<>());
sub.setId(Util.generateDbUUID());
sub.setQuantity(16L);
sub.setStartDate(TestUtil.createDate(2006, 10, 21));
sub.setEndDate(TestUtil.createDate(2020, 1, 1));
sub.setModified(new Date());
Pool sourcePool = poolManager.createAndEnrichPools(sub).get(0);
poolCurator.create(sourcePool);
Entitlement e = new Entitlement(sourcePool, consumer, owner, 1);
e.setId(Util.generateDbUUID());
entitlementCurator.create(e);
Pool pool2 = TestUtil.createPool(owner, product);
pool2.setSourceEntitlement(e);
pool2.setSourceSubscription(new SourceSubscription(sourcePool.getSubscriptionId(), "derived"));
poolCurator.create(pool2);
assertTrue(poolCurator.lookupBySubscriptionId(owner, sub.getId()).size() == 2);
poolManager.deletePool(sourcePool);
// because we check for null now, we want to verify the
// subpool gets deleted when the original pool is deleted.
Pool gone = poolCurator.find(pool2.getId());
assertEquals(gone, null);
}
use of org.candlepin.model.dto.Subscription in project candlepin by candlepin.
the class PoolCuratorTest method testMultiplierCreation.
// Note: This simply tests that the multiplier is read and used in pool creation.
// All of the null/negative multiplier test cases are in ProductTest
@Test
public void testMultiplierCreation() {
Product product = new Product("someProduct", "An Extremely Great Product", 10L);
product = this.createProduct(product, owner);
Subscription sub = TestUtil.createSubscription(owner, product, new HashSet<>());
sub.setId(Util.generateDbUUID());
sub.setQuantity(16L);
sub.setStartDate(TestUtil.createDate(2006, 10, 21));
sub.setEndDate(TestUtil.createDate(2020, 1, 1));
sub.setModified(new Date());
Pool newPool = poolManager.createAndEnrichPools(sub).get(0);
List<Pool> pools = poolCurator.lookupBySubscriptionId(owner, sub.getId());
assertEquals(160L, pools.get(0).getQuantity().longValue());
assertEquals(newPool.getQuantity(), pools.get(0).getQuantity());
}
Aggregations