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;
}
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());
}
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());
}
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());
}
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);
}
Aggregations