use of org.candlepin.dto.api.v1.ProductDTO.ProductContentDTO 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.api.v1.ProductDTO.ProductContentDTO in project candlepin by candlepin.
the class ProductManager method applyProductChanges.
/**
* Applies the changes from the given DTO to the specified entity
*
* @param entity
* The entity to modify
*
* @param update
* The DTO containing the modifications to apply
*
* @param content
* A mapping of Red Hat content ID to content entities to use for content resolution
*
* @throws IllegalArgumentException
* if entity, update or owner is null
*
* @return
* The updated product entity
*/
private Product applyProductChanges(Product entity, ProductDTO update, Map<String, Content> contentMap) {
if (entity == null) {
throw new IllegalArgumentException("entity is null");
}
if (update == null) {
throw new IllegalArgumentException("update is null");
}
if (contentMap == null) {
throw new IllegalArgumentException("contentMap is null");
}
if (update.getName() != null) {
entity.setName(update.getName());
}
if (update.getMultiplier() != null) {
entity.setMultiplier(update.getMultiplier());
}
if (update.getAttributes() != null) {
entity.setAttributes(update.getAttributes());
}
if (update.getProductContent() != null) {
Collection<ProductContent> productContent = new LinkedList<>();
// Sort the existing ProductContent so we aren't iterating on it several times.
// TODO: Remove this if/when product content is stored as a map on products.
Map<String, ProductContent> existingLinks = new HashMap<>();
for (ProductContent pc : entity.getProductContent()) {
existingLinks.put(pc.getContent().getId(), pc);
}
// Actually process our list of content...
for (ProductContentDTO pcd : update.getProductContent()) {
if (pcd == null) {
throw new IllegalStateException("Product data contains a null product-content mapping: " + update);
}
ContentDTO cdto = pcd.getContent();
if (cdto == null || cdto.getId() == null) {
// adding it to our link object. This is very bad.
throw new IllegalStateException("Product data contains an incomplete product-content " + "mapping: " + update);
}
ProductContent existingLink = existingLinks.get(cdto.getId());
Content content = contentMap.get(cdto.getId());
if (content == null) {
// Content doesn't exist yet -- it should have been created already
throw new IllegalStateException("product references content which does not exist: " + cdto);
}
if (existingLink == null) {
existingLink = new ProductContent(entity, content, pcd.isEnabled() != null ? pcd.isEnabled() : false);
} else {
existingLink.setContent(content);
if (pcd.isEnabled() != null) {
existingLink.setEnabled(pcd.isEnabled());
}
}
productContent.add(existingLink);
}
entity.setProductContent(productContent);
}
if (update.getDependentProductIds() != null) {
entity.setDependentProductIds(update.getDependentProductIds());
}
if (update.isLocked() != null) {
entity.setLocked(update.isLocked());
}
return entity;
}
use of org.candlepin.dto.api.v1.ProductDTO.ProductContentDTO in project candlepin by candlepin.
the class ProductDTOTranslatorTest method initSourceObject.
@Override
protected ProductDTO initSourceObject() {
ProductDTO source = new ProductDTO();
Map<String, String> attributes = new HashMap<>();
attributes.put("attrib_1", "attrib_value_1");
attributes.put("attrib_2", "attrib_value_2");
attributes.put("attrib_3", "attrib_value_3");
Collection<String> depProdIds = new LinkedList<>();
depProdIds.add("dep_prod_1");
depProdIds.add("dep_prod_2");
depProdIds.add("dep_prod_3");
source.setUuid("test_uuid");
source.setId("test_id");
source.setName("test_name");
source.setMultiplier(10L);
source.setAttributes(attributes);
source.setDependentProductIds(depProdIds);
for (int i = 0; i < 3; ++i) {
ContentDTO contentDTO = new ContentDTO();
contentDTO.setId("content-dto-" + i);
contentDTO.setUuid(contentDTO.getId() + "_uuid");
ProductContentDTO pcDTO = new ProductContentDTO(contentDTO, true);
source.addProductContent(pcDTO);
}
return source;
}
use of org.candlepin.dto.api.v1.ProductDTO.ProductContentDTO in project candlepin by candlepin.
the class ProductDTOTranslatorTest method verifyOutput.
@Override
protected void verifyOutput(ProductDTO source, ProductData dto, boolean childrenGenerated) {
if (source != null) {
assertEquals(source.getUuid(), dto.getUuid());
assertEquals(source.getId(), dto.getId());
assertEquals(source.getName(), dto.getName());
assertEquals(source.getMultiplier(), dto.getMultiplier());
assertEquals(source.getAttributes(), dto.getAttributes());
assertEquals(source.getDependentProductIds(), dto.getDependentProductIds());
assertNotNull(dto.getProductContent());
if (childrenGenerated) {
for (ProductContentDTO pcdto : source.getProductContent()) {
for (ProductContentData pcdata : dto.getProductContent()) {
ContentDTO cdto = pcdto.getContent();
ContentData cdata = pcdata.getContent();
assertNotNull(cdata);
assertNotNull(cdata.getUuid());
if (cdata.getUuid().equals(cdto.getUuid())) {
assertEquals(pcdto.isEnabled(), pcdata.isEnabled());
// Pass the content off to the ContentTranslatorTest to verify it
this.contentDTOTranslatorTest.verifyOutput(cdto, cdata, true);
}
}
}
} else {
assertTrue(dto.getProductContent().isEmpty());
}
} else {
assertNull(dto);
}
}
use of org.candlepin.dto.api.v1.ProductDTO.ProductContentDTO in project candlepin by candlepin.
the class ProductDataTranslatorTest method verifyOutput.
@Override
protected void verifyOutput(ProductData source, ProductDTO dto, boolean childrenGenerated) {
if (source != null) {
assertEquals(source.getUuid(), dto.getUuid());
assertEquals(source.getId(), dto.getId());
assertEquals(source.getName(), dto.getName());
assertEquals(source.getMultiplier(), dto.getMultiplier());
assertEquals(source.getAttributes(), dto.getAttributes());
assertEquals(source.getDependentProductIds(), dto.getDependentProductIds());
assertEquals(source.isLocked(), dto.isLocked());
assertEquals(source.getHref(), dto.getHref());
if (childrenGenerated) {
assertNotNull(dto.getProductContent());
for (ProductContentData pc : source.getProductContent()) {
for (ProductContentDTO pcdto : dto.getProductContent()) {
ContentData content = pc.getContent();
ContentDTO cdto = pcdto.getContent();
assertNotNull(cdto);
assertNotNull(cdto.getUuid());
if (cdto.getUuid().equals(content.getUuid())) {
assertEquals(pc.isEnabled(), pcdto.isEnabled());
// Pass the content off to the ContentTranslatorTest to verify it
this.contentDataTranslatorTest.verifyOutput(content, cdto, childrenGenerated);
}
}
}
} else {
assertNull(dto.getProductContent());
}
} else {
assertNull(dto);
}
}
Aggregations