Search in sources :

Example 1 with ProductDTO

use of org.candlepin.dto.manifest.v1.ProductDTO in project candlepin by candlepin.

the class ContentManager method updateContent.

/**
 * Updates the specified content instance, creating a new version of the content as necessary.
 * The content instance returned by this method is not guaranteed to be the same instance passed
 * in. As such, once this method has been called, callers should only use the instance output by
 * this method.
 *
 * @param owner
 *  The owner for which to update the content
 *
 * @param regenerateEntitlementCerts
 *  Whether or not changes made to the content should trigger the regeneration of entitlement
 *  certificates for affected consumers
 *
 * @throws IllegalStateException
 *  if the given content update references a content that does not exist for the specified owner
 *
 * @throws IllegalArgumentException
 *  if either the provided content entity or owner are null
 *
 * @return
 *  the updated content entity, or a new content entity
 */
@Transactional
public Content updateContent(ContentDTO update, Owner owner, boolean regenerateEntitlementCerts) {
    if (update == null) {
        throw new IllegalArgumentException("update is null");
    }
    if (update.getId() == null) {
        throw new IllegalArgumentException("update is incomplete");
    }
    if (owner == null) {
        throw new IllegalArgumentException("owner is null");
    }
    // Resolve the entity to ensure we're working with the merged entity, and to ensure it's
    // already been created.
    // TODO: FIXME:
    // There's a bug here where if changes are applied to an entity's collections, and then
    // this method is called, the check below will cause the changes to be persisted.
    // This needs to be re-written to use DTOs as the primary source of entity creation, rather
    // than a bolted-on utility method.
    // If we never edit the entity directly, however, this is safe.
    Content entity = this.ownerContentCurator.getContentById(owner, update.getId());
    if (entity == null) {
        // If we're doing an exclusive update, this should be an error condition
        throw new IllegalStateException("Content has not yet been created");
    }
    // TODO: Remove this shim and stop using DTOs in this class
    if (!this.isChangedBy(entity, update)) {
        return entity;
    }
    log.debug("Applying content update for org: {}, {}", entity, owner);
    Content updated = this.applyContentChanges((Content) entity.clone(), update);
    List<Content> alternateVersions = this.ownerContentCurator.getContentByVersions(owner, Collections.<String, Integer>singletonMap(updated.getId(), updated.getEntityVersion())).list();
    log.debug("Checking {} alternate content versions", alternateVersions.size());
    for (Content alt : alternateVersions) {
        if (alt.equals(updated)) {
            log.debug("Converging product with existing: {} => {}", updated, alt);
            // Make sure every product using the old version/entity are updated to use the new one
            List<Product> affectedProducts = this.productCurator.getProductsByContent(owner, Arrays.asList(updated.getId())).list();
            this.ownerContentCurator.updateOwnerContentReferences(owner, Collections.<String, String>singletonMap(entity.getUuid(), alt.getUuid()));
            log.debug("Updating {} affected products", affectedProducts.size());
            ContentDTO cdto = this.modelTranslator.translate(alt, ContentDTO.class);
            // TODO: Should we bulk this up like we do in importContent? Probably.
            for (Product product : affectedProducts) {
                log.debug("Updating affected product: {}", product);
                ProductDTO pdto = this.modelTranslator.translate(product, ProductDTO.class);
                ProductContentDTO pcdto = pdto.getProductContent(cdto.getId());
                if (pcdto != null) {
                    pdto.addContent(cdto, pcdto.isEnabled());
                    // Impl note: This should also take care of our entitlement cert regeneration
                    this.productManager.updateProduct(pdto, owner, regenerateEntitlementCerts);
                }
            }
            return alt;
        }
    }
    // Temporarily (?) disabled. If we ever move to clustered caching (rather than per-instance
    // caching, this branch should be re-enabled.
    /*
        // No alternate versions with which to converge. Check if we can do an in-place update instead
        if (this.ownerContentCurator.getOwnerCount(updated) < 2) {
            log.debug("Applying in-place update to content: {}", updated);

            updated = this.contentCurator.merge(this.applyContentChanges(entity, update, owner));

            if (regenerateEntitlementCerts) {
                // Every owner with a pool using any of the affected products needs an update.
                List<Product> affectedProducts = this.productCurator
                    .getProductsByContent(Arrays.asList(updated.getUuid()))
                    .list();

                this.entitlementCertGenerator.regenerateCertificatesOf(
                    Arrays.asList(owner), affectedProducts, true
                );
            }

            return updated;
        }
        */
    log.debug("Forking content and applying update: {}", updated);
    // Get products that currently use this content...
    List<Product> affectedProducts = this.productCurator.getProductsByContent(owner, Arrays.asList(updated.getId())).list();
    // Clear the UUID so Hibernate doesn't think our copy is a detached entity
    updated.setUuid(null);
    updated = this.contentCurator.create(updated);
    this.ownerContentCurator.updateOwnerContentReferences(owner, Collections.<String, String>singletonMap(entity.getUuid(), updated.getUuid()));
    // Impl note:
    // This block is a consequence of products and contents not being strongly related.
    log.debug("Updating {} affected products", affectedProducts.size());
    ContentDTO cdto = this.modelTranslator.translate(updated, ContentDTO.class);
    // TODO: Should we bulk this up like we do in importContent? Probably.
    for (Product product : affectedProducts) {
        log.debug("Updating affected product: {}", product);
        ProductDTO pdto = this.modelTranslator.translate(product, ProductDTO.class);
        ProductContentDTO pcdto = pdto.getProductContent(cdto.getId());
        if (pcdto != null) {
            pdto.addContent(cdto, pcdto.isEnabled());
            // Impl note: This should also take care of our entitlement cert regeneration
            this.productManager.updateProduct(pdto, owner, regenerateEntitlementCerts);
        }
    }
    return updated;
}
Also used : ProductContentDTO(org.candlepin.dto.api.v1.ProductDTO.ProductContentDTO) ContentDTO(org.candlepin.dto.api.v1.ContentDTO) ProductContent(org.candlepin.model.ProductContent) Content(org.candlepin.model.Content) OwnerContent(org.candlepin.model.OwnerContent) Product(org.candlepin.model.Product) ProductContentDTO(org.candlepin.dto.api.v1.ProductDTO.ProductContentDTO) ProductDTO(org.candlepin.dto.api.v1.ProductDTO) Transactional(com.google.inject.persist.Transactional)

Example 2 with ProductDTO

use of org.candlepin.dto.manifest.v1.ProductDTO in project candlepin by candlepin.

the class EntitlementImporterTest method fullImport.

@Test
public void fullImport() throws Exception {
    Product parentProduct = TestUtil.createProduct();
    Product derivedProduct = TestUtil.createProduct();
    Product provided1 = TestUtil.createProduct();
    Set<Product> providedProducts = new HashSet<>();
    providedProducts.add(new Product(provided1));
    Product derivedProvided1 = TestUtil.createProduct();
    Set<Product> derivedProvidedProducts = new HashSet<>();
    derivedProvidedProducts.add(new Product(derivedProvided1));
    Pool pool = TestUtil.createPool(owner, parentProduct, new HashSet<>(), derivedProduct, new HashSet<>(), 3);
    pool.setProvidedProducts(providedProducts);
    pool.setDerivedProvidedProducts(derivedProvidedProducts);
    Entitlement ent = TestUtil.createEntitlement(owner, consumer, pool, cert);
    ent.setQuantity(3);
    EntitlementDTO dtoEnt = this.translator.translate(ent, EntitlementDTO.class);
    when(om.readValue(reader, EntitlementDTO.class)).thenReturn(dtoEnt);
    // Create our expected products
    Map<String, ProductDTO> productsById = buildProductCache(parentProduct, provided1, derivedProduct, derivedProvided1);
    Subscription sub = importer.importObject(om, reader, owner, productsById, consumerDTO.getUuid(), meta);
    assertEquals(pool.getId(), sub.getUpstreamPoolId());
    assertEquals(consumer.getUuid(), sub.getUpstreamConsumerId());
    assertEquals(ent.getId(), sub.getUpstreamEntitlementId());
    assertEquals(owner, sub.getOwner());
    assertEquals(ent.getStartDate(), sub.getStartDate());
    assertEquals(ent.getEndDate(), sub.getEndDate());
    assertEquals(pool.getAccountNumber(), sub.getAccountNumber());
    assertEquals(pool.getContractNumber(), sub.getContractNumber());
    assertEquals(pool.getOrderNumber(), sub.getOrderNumber());
    assertEquals(ent.getQuantity().intValue(), sub.getQuantity().intValue());
    assertEquals(parentProduct.toDTO(), sub.getProduct());
    assertEquals(providedProducts.size(), sub.getProvidedProducts().size());
    assertEquals(provided1.getId(), sub.getProvidedProducts().iterator().next().getId());
    assertEquals(derivedProduct.toDTO(), sub.getDerivedProduct());
    assertEquals(1, sub.getDerivedProvidedProducts().size());
    assertEquals(derivedProvided1.getId(), sub.getDerivedProvidedProducts().iterator().next().getId());
    assertNotNull(sub.getCertificate());
    CertificateSerial serial = sub.getCertificate().getSerial();
    assertEquals(cert.getSerial().isCollected(), serial.isCollected());
    assertEquals(cert.getSerial().getExpiration(), serial.getExpiration());
    assertEquals(cert.getSerial().getCreated(), serial.getCreated());
    assertEquals(cert.getSerial().getUpdated(), serial.getUpdated());
    assertEquals(sub.getCdn().getLabel(), meta.getCdnLabel());
}
Also used : EntitlementDTO(org.candlepin.dto.manifest.v1.EntitlementDTO) Product(org.candlepin.model.Product) CertificateSerial(org.candlepin.model.CertificateSerial) Pool(org.candlepin.model.Pool) Entitlement(org.candlepin.model.Entitlement) Subscription(org.candlepin.model.dto.Subscription) ProductDTO(org.candlepin.dto.manifest.v1.ProductDTO) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 3 with ProductDTO

use of org.candlepin.dto.manifest.v1.ProductDTO in project candlepin by candlepin.

the class ProductImporterTest method testCreateObject.

@Test
public void testCreateObject() throws Exception {
    Product product = TestUtil.createProduct();
    product.setAttribute("a1", "a1");
    product.setAttribute("a2", "a2");
    String json = getJsonForProduct(product);
    Reader reader = new StringReader(json);
    ProductDTO created = importer.createObject(mapper, reader, owner);
    assertEquals(product.getUuid(), created.getUuid());
    assertEquals(product.getName(), created.getName());
    assertEquals(product.getAttributes(), created.getAttributes());
}
Also used : StringReader(java.io.StringReader) Product(org.candlepin.model.Product) Reader(java.io.Reader) StringReader(java.io.StringReader) ProductDTO(org.candlepin.dto.manifest.v1.ProductDTO) Test(org.junit.Test)

Example 4 with ProductDTO

use of org.candlepin.dto.manifest.v1.ProductDTO in project candlepin by candlepin.

the class ProductImporterTest method testContentCreated.

@Test
public void testContentCreated() throws Exception {
    Product product = TestUtil.createProduct();
    addContentTo(product);
    String json = getJsonForProduct(product);
    Reader reader = new StringReader(json);
    ProductDTO created = importer.createObject(mapper, reader, owner);
    ContentDTO c = created.getProductContent().iterator().next().getContent();
    // Metadata expiry should be overridden to 0 on import:
    assertEquals(new Long(1), c.getMetadataExpire());
}
Also used : ContentDTO(org.candlepin.dto.manifest.v1.ContentDTO) StringReader(java.io.StringReader) Product(org.candlepin.model.Product) Reader(java.io.Reader) StringReader(java.io.StringReader) ProductDTO(org.candlepin.dto.manifest.v1.ProductDTO) Test(org.junit.Test)

Example 5 with ProductDTO

use of org.candlepin.dto.manifest.v1.ProductDTO in project candlepin by candlepin.

the class HostedTestSubscriptionResource method addBatchContent.

@POST
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Path("/owners/{owner_key}/products/{product_id}/batch_content")
@Transactional
public ProductDTO addBatchContent(@PathParam("owner_key") String ownerKey, @PathParam("product_id") String productId, Map<String, Boolean> contentMap) {
    Owner owner = this.getOwnerByKey(ownerKey);
    Product product = this.fetchProduct(owner, productId);
    Collection<ProductContent> productContent = new LinkedList<>();
    ProductDTO pdto = this.translator.translate(product, ProductDTO.class);
    // Impl note:
    // This is a wholely inefficient way of doing this. When we return to using ID-based linking
    // and we're not linking the universe with our model, we can just attach the IDs directly
    // without needing all this DTO conversion back and forth.
    // Alternatively, we can shut off Hibernate's auto-commit junk and get in the habit of
    // calling commit methods as necessary so we don't have to work with DTOs internally.
    boolean changed = false;
    for (Entry<String, Boolean> entry : contentMap.entrySet()) {
        Content content = this.fetchContent(owner, entry.getKey());
        boolean enabled = entry.getValue() != null ? entry.getValue() : ProductContent.DEFAULT_ENABLED_STATE;
        ContentDTO cdto = this.translator.translate(content, ContentDTO.class);
        changed |= pdto.addContent(cdto, enabled);
        addContentToUpstreamSubscriptions(product, content, enabled);
    }
    if (changed) {
        product = this.productManager.updateProduct(pdto, owner, true);
    }
    return this.translator.translate(product, ProductDTO.class);
}
Also used : ContentDTO(org.candlepin.dto.api.v1.ContentDTO) Owner(org.candlepin.model.Owner) ProductContent(org.candlepin.model.ProductContent) Content(org.candlepin.model.Content) Product(org.candlepin.model.Product) ProductContent(org.candlepin.model.ProductContent) LinkedList(java.util.LinkedList) ProductDTO(org.candlepin.dto.api.v1.ProductDTO) Path(javax.ws.rs.Path) POST(javax.ws.rs.POST) Consumes(javax.ws.rs.Consumes) Produces(javax.ws.rs.Produces) Transactional(com.google.inject.persist.Transactional)

Aggregations

ProductDTO (org.candlepin.dto.api.v1.ProductDTO)29 Product (org.candlepin.model.Product)27 Test (org.junit.Test)27 Owner (org.candlepin.model.Owner)25 ProductDTO (org.candlepin.dto.manifest.v1.ProductDTO)12 Content (org.candlepin.model.Content)10 ProductContent (org.candlepin.model.ProductContent)9 ContentDTO (org.candlepin.dto.api.v1.ContentDTO)7 Parameters (junitparams.Parameters)6 ContentDTO (org.candlepin.dto.manifest.v1.ContentDTO)6 Transactional (com.google.inject.persist.Transactional)5 Reader (java.io.Reader)5 StringReader (java.io.StringReader)4 HashSet (java.util.HashSet)4 LinkedList (java.util.LinkedList)4 Subscription (org.candlepin.model.dto.Subscription)4 Consumes (javax.ws.rs.Consumes)3 Path (javax.ws.rs.Path)3 Produces (javax.ws.rs.Produces)3 ForbiddenException (org.candlepin.common.exceptions.ForbiddenException)3