Search in sources :

Example 16 with ProductData

use of org.candlepin.model.dto.ProductData in project candlepin by candlepin.

the class EntitlerTest method testCreatedDevPoolAttributes.

@Test
public void testCreatedDevPoolAttributes() {
    Owner owner = TestUtil.createOwner("o");
    List<ProductData> devProdDTOs = new ArrayList<>();
    Product p1 = TestUtil.createProduct("dev-product", "Dev Product");
    p1.setAttribute(Product.Attributes.SUPPORT_LEVEL, "Premium");
    p1.setAttribute("expires_after", "47");
    Product p2 = TestUtil.createProduct("provided-product1", "Provided Product 1");
    Product p3 = TestUtil.createProduct("provided-product2", "Provided Product 2");
    devProdDTOs.add(p1.toDTO());
    devProdDTOs.add(p2.toDTO());
    devProdDTOs.add(p3.toDTO());
    Consumer devSystem = TestUtil.createConsumer(owner);
    devSystem.setFact("dev_sku", p1.getId());
    devSystem.addInstalledProduct(new ConsumerInstalledProduct(p2));
    devSystem.addInstalledProduct(new ConsumerInstalledProduct(p3));
    when(productAdapter.getProductsByIds(eq(owner), any(List.class))).thenReturn(devProdDTOs);
    this.mockProducts(owner, p1, p2, p3);
    this.mockProductImport(owner, p1, p2, p3);
    this.mockContentImport(owner, Collections.<String, Content>emptyMap());
    Pool created = entitler.assembleDevPool(devSystem, owner, devSystem.getFact("dev_sku"));
    Calendar cal = Calendar.getInstance();
    cal.setTime(created.getStartDate());
    cal.add(Calendar.DAY_OF_YEAR, 47);
    assertEquals(created.getEndDate(), cal.getTime());
    assertEquals("true", created.getAttributeValue(Pool.Attributes.DEVELOPMENT_POOL));
    assertEquals(devSystem.getUuid(), created.getAttributeValue(Pool.Attributes.REQUIRES_CONSUMER));
    assertEquals(p1.getId(), created.getProductId());
    assertEquals(2, created.getProvidedProducts().size());
    assertEquals("Premium", created.getProduct().getAttributeValue(Product.Attributes.SUPPORT_LEVEL));
    assertEquals(1L, created.getQuantity().longValue());
}
Also used : ProductData(org.candlepin.model.dto.ProductData) Owner(org.candlepin.model.Owner) Consumer(org.candlepin.model.Consumer) ConsumerInstalledProduct(org.candlepin.model.ConsumerInstalledProduct) Calendar(java.util.Calendar) ArrayList(java.util.ArrayList) Product(org.candlepin.model.Product) ConsumerInstalledProduct(org.candlepin.model.ConsumerInstalledProduct) List(java.util.List) ArrayList(java.util.ArrayList) Pool(org.candlepin.model.Pool) Test(org.junit.Test)

Example 17 with ProductData

use of org.candlepin.model.dto.ProductData in project candlepin by candlepin.

the class EntitlementImporter method associateProvidedProducts.

/*
     * Transfer associations to provided and derived provided products over to the
     * subscription.
     *
     * WARNING: This is a bit tricky due to backward compatibility issues. Prior to
     * candlepin 2.0, pools serialized a collection of disjoint provided product info,
     * an object with just a product ID and name, not directly linked to anything in the db.
     *
     * In candlepin 2.0 we have referential integrity and links to full product objects,
     * but we need to maintain both API and import compatibility with old manifests and
     * servers that may import new manifests.
     *
     * To do this, we serialize the providedProductDtos and derivedProvidedProductDtos
     * collections on pool which keeps the API/manifest JSON identical to what it was
     * before. On import we load into these transient collections, and here we transfer
     * to the actual persisted location.
     */
public void associateProvidedProducts(Map<String, ProductDTO> productsById, Entitlement entitlement, Subscription subscription) throws SyncDataFormatException {
    // Associate main provided products:
    Set<ProductData> providedProducts = new HashSet<>();
    entitlement.getPool().populateAllTransientProvidedProducts(productCurator);
    for (ProvidedProduct providedProduct : entitlement.getPool().getProvidedProductDtos()) {
        ProductDTO productDTO = this.findProduct(productsById, providedProduct.getProductId());
        providedProducts.add(this.translator.translate(productDTO, ProductData.class));
    }
    subscription.setProvidedProducts(providedProducts);
    // Associate derived provided products:
    Set<ProductData> derivedProvidedProducts = new HashSet<>();
    for (ProvidedProduct pp : entitlement.getPool().getDerivedProvidedProductDtos()) {
        ProductDTO productDTO = this.findProduct(productsById, pp.getProductId());
        derivedProvidedProducts.add(this.translator.translate(productDTO, ProductData.class));
    }
    subscription.setDerivedProvidedProducts(derivedProvidedProducts);
    log.debug("Subscription has {} provided products.", derivedProvidedProducts.size());
    log.debug("Subscription has {} derived provided products.", derivedProvidedProducts.size());
}
Also used : ProductData(org.candlepin.model.dto.ProductData) ProvidedProduct(org.candlepin.model.ProvidedProduct) ProductDTO(org.candlepin.dto.manifest.v1.ProductDTO) HashSet(java.util.HashSet)

Example 18 with ProductData

use of org.candlepin.model.dto.ProductData in project candlepin by candlepin.

the class PoolRulesTest method createVirtLimitSubWithDerivedProducts.

private Subscription createVirtLimitSubWithDerivedProducts(String productId, String derivedProductId, int quantity, int virtLimit) {
    Product product = TestUtil.createProduct(productId, productId);
    product.setAttribute(Product.Attributes.VIRT_LIMIT, Integer.toString(virtLimit));
    when(ownerProdCuratorMock.getProductById(owner, product.getId())).thenReturn(product);
    Product derivedProd = TestUtil.createProduct(derivedProductId, derivedProductId);
    // We'll look for this to make sure it makes it to correct pools:
    derivedProd.setAttribute(DERIVED_ATTR, "nobodycares");
    when(ownerProdCuratorMock.getProductById(owner, derivedProd.getId())).thenReturn(derivedProd);
    // Create some provided products:
    Product provided1 = TestUtil.createProduct();
    when(ownerProdCuratorMock.getProductById(owner, provided1.getId())).thenReturn(provided1);
    Product provided2 = TestUtil.createProduct();
    when(ownerProdCuratorMock.getProductById(owner, provided2.getId())).thenReturn(provided2);
    // Create some derived provided products:
    Product derivedProvided1 = TestUtil.createProduct();
    when(ownerProdCuratorMock.getProductById(owner, derivedProvided1.getId())).thenReturn(derivedProvided1);
    Product derivedProvided2 = TestUtil.createProduct();
    when(ownerProdCuratorMock.getProductById(owner, derivedProvided2.getId())).thenReturn(derivedProvided2);
    Subscription s = TestUtil.createSubscription(owner, product);
    s.setQuantity(new Long(quantity));
    s.setDerivedProduct(derivedProd.toDTO());
    Set<ProductData> derivedProds = new HashSet<>();
    derivedProds.add(derivedProvided1.toDTO());
    derivedProds.add(derivedProvided2.toDTO());
    s.setDerivedProvidedProducts(derivedProds);
    return s;
}
Also used : ProductData(org.candlepin.model.dto.ProductData) Product(org.candlepin.model.Product) Subscription(org.candlepin.model.dto.Subscription) HashSet(java.util.HashSet)

Example 19 with ProductData

use of org.candlepin.model.dto.ProductData in project candlepin by candlepin.

the class ContentManager method importContent.

/**
 * Creates or updates content from the given content DTOs, omitting product updates for the
 * provided Red Hat product IDs.
 * <p></p>
 * The content DTOs provided in the given map should be mapped by the content's Red Hat ID. If
 * the mappings are incorrect or inconsistent, the result of this method is undefined.
 *
 * @param owner
 *  The owner for which to import the given content
 *
 * @param contentData
 *  A mapping of Red Hat content ID to content DTOs to import
 *
 * @param importedProductIds
 *  A set of Red Hat product IDs specifying products which are being imported and should not be
 *  updated as part of this import operation
 *
 * @return
 *  A mapping of Red Hat content ID to content entities representing the imported content
 */
@SuppressWarnings("checkstyle:methodlength")
@Transactional
@Traceable
public ImportResult<Content> importContent(@TraceableParam("owner") Owner owner, Map<String, ContentData> contentData, Set<String> importedProductIds) {
    if (owner == null) {
        throw new IllegalArgumentException("owner is null");
    }
    ImportResult<Content> importResult = new ImportResult<>();
    if (contentData == null || contentData.isEmpty()) {
        // Nothing to import
        return importResult;
    }
    Map<String, Content> skippedContent = importResult.getSkippedEntities();
    Map<String, Content> createdContent = importResult.getCreatedEntities();
    Map<String, Content> updatedContent = importResult.getUpdatedEntities();
    Map<String, Integer> contentVersions = new HashMap<>();
    Map<String, Content> sourceContent = new HashMap<>();
    Map<String, List<Content>> existingVersions = new HashMap<>();
    List<OwnerContent> ownerContentBuffer = new LinkedList<>();
    // - Divide imported products into sets of updates and creates
    log.debug("Fetching existing content for update...");
    for (Content content : this.ownerContentCurator.getContentByIds(owner, contentData.keySet())) {
        ContentData update = contentData.get(content.getId());
        if (!this.isChangedBy(content, update)) {
            // This content won't be changing, so we'll just pretend it's not being imported at all
            skippedContent.put(content.getId(), content);
            continue;
        }
        // Content is coming from an upstream source; lock it so only upstream can make
        // further changes to it. If we ever use this method for anything other than
        // imports, we'll need to stop doing this.
        sourceContent.put(content.getId(), content);
        content = this.applyContentChanges((Content) content.clone(), update);
        updatedContent.put(content.getId(), content);
        contentVersions.put(content.getId(), content.getEntityVersion());
    }
    log.debug("Validating new content...");
    for (ContentData update : contentData.values()) {
        if (!skippedContent.containsKey(update.getId()) && !updatedContent.containsKey(update.getId())) {
            // Ensure content is minimally populated
            if (update.getId() == null || update.getType() == null || update.getLabel() == null || update.getName() == null || update.getVendor() == null) {
                throw new IllegalStateException("Content data is incomplete: " + update);
            }
            Content content = this.applyContentChanges(new Content(update.getId()), update);
            createdContent.put(content.getId(), content);
            contentVersions.put(content.getId(), content.getEntityVersion());
        }
    }
    log.debug("Checking for existing content versions...");
    for (Content alt : this.ownerContentCurator.getContentByVersions(owner, contentVersions)) {
        List<Content> alternates = existingVersions.get(alt.getId());
        if (alternates == null) {
            alternates = new LinkedList<>();
            existingVersions.put(alt.getId(), alternates);
        }
        alternates.add(alt);
    }
    contentVersions.clear();
    contentVersions = null;
    // We're about to start modifying the maps, so we need to clone the created set before we
    // start adding the update forks to it.
    Map<String, Content> stagedEntities = new HashMap<>(createdContent);
    // Process the created group...
    // Check our created set for existing versions:
    // - If there's an existing version, we'll remove the staged entity from the creation
    // set, and stage an owner-content mapping for the existing version
    // - Otherwise, we'll stage the new entity for persistence by leaving it in the created
    // set, and stage an owner-content mapping to the new entity
    Iterator<Content> iterator = stagedEntities.values().iterator();
    createdContentLoop: while (iterator.hasNext()) {
        Content created = iterator.next();
        List<Content> alternates = existingVersions.get(created.getId());
        if (alternates != null) {
            for (Content alt : alternates) {
                if (created.equals(alt)) {
                    ownerContentBuffer.add(new OwnerContent(owner, alt));
                    createdContent.put(alt.getId(), alt);
                    iterator.remove();
                    continue createdContentLoop;
                }
            }
        }
        ownerContentBuffer.add(new OwnerContent(owner, created));
    }
    // - Otherwise, we need to stage the updated entity for persistence
    updatedContentLoop: for (Map.Entry<String, Content> entry : updatedContent.entrySet()) {
        Content updated = entry.getValue();
        List<Content> alternates = existingVersions.get(updated.getId());
        if (alternates != null) {
            for (Content alt : alternates) {
                if (!updated.getUuid().equals(alt.getUuid()) && updated.equals(alt)) {
                    updated = alt;
                    entry.setValue(alt);
                    continue updatedContentLoop;
                }
            }
        }
        // We need to stage the updated entity for persistence. We'll reuse the now-empty
        // createdContent map for this.
        updated.setUuid(null);
        stagedEntities.put(updated.getId(), updated);
    }
    // Persist our staged entities
    // We probably don't want to evict the content yet, as they'll appear as unmanaged if
    // they're used later. However, the join objects can be evicted safely since they're only
    // really used here.
    log.debug("Persisting content changes...");
    this.contentCurator.saveAll(stagedEntities.values(), true, false);
    this.ownerContentCurator.saveAll(ownerContentBuffer, true, true);
    // Fetch collection of products affected by this import that aren't being imported themselves
    log.debug("Updating non-imported, affected products...");
    List<Product> affectedProducts = this.productCurator.getProductsByContent(owner, sourceContent.keySet(), importedProductIds).list();
    if (affectedProducts != null && !affectedProducts.isEmpty()) {
        // Get the collection of content those products use
        Map<String, Content> affectedProductsContent = new HashMap<>();
        for (Content content : this.contentCurator.getContentByProducts(affectedProducts)) {
            affectedProductsContent.put(content.getId(), content);
        }
        // Update the content map so it references the updated content
        affectedProductsContent.putAll(updatedContent);
        Map<String, ProductData> affectedProductData = new HashMap<>();
        Map<String, ContentData> contentDTOCache = new HashMap<>();
        for (Product product : affectedProducts) {
            ProductData pdto = product.toDTO();
            for (ProductContent pcdata : product.getProductContent()) {
                Content content = pcdata.getContent();
                Content updated = updatedContent.get(content.getId());
                if (updated != null) {
                    ContentData cdto = contentDTOCache.get(content.getId());
                    if (cdto == null) {
                        cdto = content.toDTO();
                        contentDTOCache.put(cdto.getId(), cdto);
                    }
                    pdto.addContent(cdto, pcdata.isEnabled());
                }
            }
            affectedProductData.put(pdto.getId(), pdto);
        }
        // Perform a micro-import for these products using the content map we just built
        this.productManager.importProducts(owner, affectedProductData, affectedProductsContent);
    }
    // Perform bulk reference update
    Map<String, String> contentUuidMap = new HashMap<>();
    for (Content update : updatedContent.values()) {
        Content source = sourceContent.get(update.getId());
        contentUuidMap.put(source.getUuid(), update.getUuid());
    }
    this.ownerContentCurator.updateOwnerContentReferences(owner, contentUuidMap);
    // Return
    return importResult;
}
Also used : OwnerContent(org.candlepin.model.OwnerContent) HashMap(java.util.HashMap) Product(org.candlepin.model.Product) ContentData(org.candlepin.model.dto.ContentData) ProductContentData(org.candlepin.model.dto.ProductContentData) LinkedList(java.util.LinkedList) List(java.util.List) ProductData(org.candlepin.model.dto.ProductData) LinkedList(java.util.LinkedList) ProductContent(org.candlepin.model.ProductContent) ProductContent(org.candlepin.model.ProductContent) Content(org.candlepin.model.Content) OwnerContent(org.candlepin.model.OwnerContent) Traceable(org.candlepin.util.Traceable) Transactional(com.google.inject.persist.Transactional)

Example 20 with ProductData

use of org.candlepin.model.dto.ProductData in project candlepin by candlepin.

the class ContentManager method removeContentByUuids.

/**
 * Removes all content with the provided UUIDs from the given owner.
 *
 * @param owner
 *  The owner from which to remove content
 *
 * @param contentUuids
 *  A collection of UUIDs representing the content to remove
 *
 * @param regenerateEntitlementCerts
 *  Whether or not changes made to the content should trigger the regeneration of entitlement
 *  certificates for affected consumers
 *
 * @throws IllegalArgumentException
 *  if owner is null
 */
public void removeContentByUuids(Owner owner, Collection<String> contentUuids, boolean regenerateEntitlementCerts) {
    if (owner == null) {
        throw new IllegalArgumentException("owner is null");
    }
    if (contentUuids != null && !contentUuids.isEmpty()) {
        log.debug("Deleting content with UUIDs: {}", contentUuids);
        List<Product> affectedProducts = this.productCurator.getProductsByContentUuids(owner, contentUuids).list();
        if (!affectedProducts.isEmpty()) {
            log.debug("Updating {} affected products", affectedProducts.size());
            if (!(contentUuids instanceof Set)) {
                // Convert this to a set so our filtering lookups aren't painfully slow
                contentUuids = new HashSet<>(contentUuids);
            }
            // Get the collection of content those products use, throwing out the ones we'll be
            // removing shortly
            Map<String, Content> affectedProductsContent = new HashMap<>();
            for (Content content : this.contentCurator.getContentByProducts(affectedProducts)) {
                if (!contentUuids.contains(content.getUuid())) {
                    affectedProductsContent.put(content.getId(), content);
                }
            }
            // Convert our affectedProducts into DTOs (hoping Hibernate uses its entity cache
            // instead of pulling down the content list for each product...)
            Map<String, ProductData> affectedProductData = new HashMap<>();
            for (Product product : affectedProducts) {
                ProductData pdto = product.toDTO();
                Iterator<ProductContentData> pcd = pdto.getProductContent().iterator();
                while (pcd.hasNext()) {
                    ContentData cdto = pcd.next().getContent();
                    if (!affectedProductsContent.containsKey(cdto.getId())) {
                        pcd.remove();
                    }
                }
                affectedProductData.put(pdto.getId(), pdto);
            }
            // Perform a micro-import for these products using the content map we just built
            log.debug("Performing micro-import for products: {}", affectedProductData);
            this.productManager.importProducts(owner, affectedProductData, affectedProductsContent);
            if (regenerateEntitlementCerts) {
                this.entitlementCertGenerator.regenerateCertificatesOf(Arrays.asList(owner), affectedProducts, true);
            }
        }
        // Remove content references
        this.ownerContentCurator.removeOwnerContentReferences(owner, contentUuids);
    }
}
Also used : ProductData(org.candlepin.model.dto.ProductData) HashSet(java.util.HashSet) Set(java.util.Set) HashMap(java.util.HashMap) Product(org.candlepin.model.Product) ContentData(org.candlepin.model.dto.ContentData) ProductContentData(org.candlepin.model.dto.ProductContentData) ProductContent(org.candlepin.model.ProductContent) Content(org.candlepin.model.Content) OwnerContent(org.candlepin.model.OwnerContent) ProductContentData(org.candlepin.model.dto.ProductContentData)

Aggregations

ProductData (org.candlepin.model.dto.ProductData)30 Product (org.candlepin.model.Product)22 Pool (org.candlepin.model.Pool)13 Owner (org.candlepin.model.Owner)12 Test (org.junit.Test)12 ArrayList (java.util.ArrayList)11 List (java.util.List)10 ConsumerInstalledProduct (org.candlepin.model.ConsumerInstalledProduct)10 HashSet (java.util.HashSet)9 HashMap (java.util.HashMap)8 SourceSubscription (org.candlepin.model.SourceSubscription)8 Subscription (org.candlepin.model.dto.Subscription)8 Date (java.util.Date)7 Consumer (org.candlepin.model.Consumer)7 LinkedList (java.util.LinkedList)5 Content (org.candlepin.model.Content)5 ProductContentData (org.candlepin.model.dto.ProductContentData)5 AutobindData (org.candlepin.resource.dto.AutobindData)5 Map (java.util.Map)4 ContentData (org.candlepin.model.dto.ContentData)4