use of com.haulmont.cuba.core.app.events.EntityChangedEvent in project cuba by cuba-platform.
the class RdbmsStore method commit.
@Override
@SuppressWarnings("unchecked")
public Set<Entity> commit(CommitContext context) {
if (log.isDebugEnabled())
log.debug("commit: commitInstances=" + context.getCommitInstances() + ", removeInstances=" + context.getRemoveInstances());
Set<Entity> saved = new HashSet<>();
List<Entity> persisted = new ArrayList<>();
List<BaseGenericIdEntity> identityEntitiesToStoreDynamicAttributes = new ArrayList<>();
List<CategoryAttributeValue> attributeValuesToRemove = new ArrayList<>();
EntityManager em = null;
boolean softDeletionBefore;
SavedEntitiesHolder savedEntitiesHolder;
try (Transaction tx = getSaveTransaction(storeName, context.isJoinTransaction())) {
em = persistence.getEntityManager(storeName);
checkPermissions(context);
softDeletionBefore = em.isSoftDeletion();
em.setSoftDeletion(context.isSoftDeletion());
List<BaseGenericIdEntity> entitiesToStoreDynamicAttributes = new ArrayList<>();
// persist new
for (Entity entity : context.getCommitInstances()) {
if (entityStates.isNew(entity)) {
if (isAuthorizationRequired(context)) {
attributeSecurity.beforePersist(entity);
}
em.persist(entity);
saved.add(entity);
persisted.add(entity);
if (isAuthorizationRequired(context))
checkOperationPermitted(entity, EntityOp.CREATE);
if (!context.isDiscardCommitted()) {
View view = getViewFromContextOrNull(context, entity);
entityFetcher.fetch(entity, view, true);
attributeSecurity.afterPersist(entity, view);
}
if (entityHasDynamicAttributes(entity)) {
if (entity instanceof BaseDbGeneratedIdEntity) {
identityEntitiesToStoreDynamicAttributes.add((BaseGenericIdEntity) entity);
} else {
entitiesToStoreDynamicAttributes.add((BaseGenericIdEntity) entity);
}
}
}
}
// merge the rest - instances can be detached or not
for (Entity entity : context.getCommitInstances()) {
if (!entityStates.isNew(entity)) {
if (isAuthorizationRequired(context)) {
security.assertToken(entity);
}
security.restoreSecurityStateAndFilteredData(entity);
if (isAuthorizationRequired(context)) {
attributeSecurity.beforeMerge(entity);
}
Entity merged = em.merge(entity);
saved.add(merged);
entityFetcher.fetch(merged, getViewFromContext(context, entity));
attributeSecurity.afterMerge(merged);
if (isAuthorizationRequired(context))
checkOperationPermitted(merged, EntityOp.UPDATE);
if (entityHasDynamicAttributes(entity)) {
BaseGenericIdEntity originalBaseGenericIdEntity = (BaseGenericIdEntity) entity;
BaseGenericIdEntity mergedBaseGenericIdEntity = (BaseGenericIdEntity) merged;
mergeDynamicAttributes(originalBaseGenericIdEntity, mergedBaseGenericIdEntity);
entitiesToStoreDynamicAttributes.add(mergedBaseGenericIdEntity);
}
}
}
for (BaseGenericIdEntity entity : entitiesToStoreDynamicAttributes) {
dynamicAttributesManagerAPI.storeDynamicAttributes(entity);
}
// remove
for (Entity entity : context.getRemoveInstances()) {
if (isAuthorizationRequired(context)) {
security.assertToken(entity);
}
security.restoreSecurityStateAndFilteredData(entity);
Entity e;
if (entity instanceof SoftDelete) {
attributeSecurity.beforeMerge(entity);
e = em.merge(entity);
entityFetcher.fetch(e, getViewFromContext(context, entity));
attributeSecurity.afterMerge(e);
} else {
e = em.merge(entity);
}
if (isAuthorizationRequired(context))
checkOperationPermitted(e, EntityOp.DELETE);
em.remove(e);
saved.add(e);
if (entityHasDynamicAttributes(entity)) {
Map<String, CategoryAttributeValue> dynamicAttributes = ((BaseGenericIdEntity) entity).getDynamicAttributes();
// old values of dynamic attributes on deleted entity are used in EntityChangedEvent
((BaseGenericIdEntity) e).setDynamicAttributes(dynamicAttributes);
// noinspection ConstantConditions
for (CategoryAttributeValue categoryAttributeValue : dynamicAttributes.values()) {
if (!entityStates.isNew(categoryAttributeValue)) {
if (Stores.isMain(storeName)) {
em.remove(categoryAttributeValue);
} else {
attributeValuesToRemove.add(categoryAttributeValue);
}
saved.add(categoryAttributeValue);
}
}
}
}
if (!context.isDiscardCommitted() && isAuthorizationRequired(context) && userSessionSource.getUserSession().getConstraints().exists()) {
security.calculateFilteredData(saved);
}
savedEntitiesHolder = SavedEntitiesHolder.setEntities(saved);
if (context.isJoinTransaction()) {
List<EntityChangedEventInfo> eventsInfo = entityChangedEventManager.collect(saved);
persistenceSupport.processFlush(em, false);
em.getDelegate().flush();
List<EntityChangedEvent> events = new ArrayList<>(eventsInfo.size());
for (EntityChangedEventInfo info : eventsInfo) {
events.add(new EntityChangedEvent(info.getSource(), Id.of(info.getEntity()), info.getType(), info.getChanges()));
}
for (Entity entity : saved) {
detachEntity(em, entity, getViewFromContext(context, entity));
}
entityChangedEventManager.publish(events);
}
tx.commit();
if (em != null) {
em.setSoftDeletion(softDeletionBefore);
}
}
if (!attributeValuesToRemove.isEmpty()) {
try (Transaction tx = getSaveTransaction(Stores.MAIN, context.isJoinTransaction())) {
EntityManager entityManager = persistence.getEntityManager();
for (CategoryAttributeValue entity : attributeValuesToRemove) {
entityManager.remove(entity);
}
tx.commit();
}
}
if (!identityEntitiesToStoreDynamicAttributes.isEmpty()) {
try (Transaction tx = getSaveTransaction(storeName, context.isJoinTransaction())) {
for (BaseGenericIdEntity entity : identityEntitiesToStoreDynamicAttributes) {
dynamicAttributesManagerAPI.storeDynamicAttributes(entity);
}
tx.commit();
}
}
Set<Entity> resultEntities = savedEntitiesHolder.getEntities(saved);
reloadIfUnfetched(resultEntities, context);
if (!context.isDiscardCommitted() && isAuthorizationRequired(context) && userSessionSource.getUserSession().getConstraints().exists()) {
security.applyConstraints(resultEntities);
}
if (!context.isDiscardCommitted()) {
if (isAuthorizationRequired(context)) {
for (Entity entity : resultEntities) {
if (!persisted.contains(entity)) {
attributeSecurity.afterCommit(entity);
}
}
}
// Update references from newly persisted entities to merged detached entities. Otherwise a new entity can
// contain a stale instance of a merged one.
entityReferencesNormalizer.updateReferences(persisted, resultEntities);
}
return context.isDiscardCommitted() ? Collections.emptySet() : resultEntities;
}
use of com.haulmont.cuba.core.app.events.EntityChangedEvent in project cuba by cuba-platform.
the class EntityChangedEventManager method internalCollect.
public List<EntityChangedEventInfo> internalCollect(Collection<Entity> entities) {
List<EntityChangedEventInfo> list = new ArrayList<>();
for (Entity entity : entities) {
PublishingInfo info = infoCache.computeIfAbsent(entity.getClass(), aClass -> {
MetaClass metaClass = metadata.getClassNN(entity.getClass());
Map attrMap = (Map) metaClass.getAnnotations().get(PublishEntityChangedEvents.class.getName());
if (attrMap != null) {
if (!(entity instanceof BaseGenericIdEntity)) {
log.warn("Cannot publish EntityChangedEvent for {} because it is not a BaseGenericIdEntity", entity);
} else {
return new PublishingInfo(Boolean.TRUE.equals(attrMap.get("created")), Boolean.TRUE.equals(attrMap.get("updated")), Boolean.TRUE.equals(attrMap.get("deleted")));
}
}
return new PublishingInfo();
});
if (info.publish) {
EntityChangedEvent.Type type = null;
AttributeChanges attributeChanges = null;
if (info.onCreated && BaseEntityInternalAccess.isNew((BaseGenericIdEntity) entity)) {
type = EntityChangedEvent.Type.CREATED;
attributeChanges = getEntityAttributeChanges(entity, false);
} else {
if (info.onUpdated || info.onDeleted) {
AttributeChangeListener changeListener = (AttributeChangeListener) ((ChangeTracker) entity)._persistence_getPropertyChangeListener();
if (changeListener == null) {
log.trace("Cannot publish EntityChangedEvent for {} because its AttributeChangeListener is null", entity);
continue;
}
if (info.onDeleted && PersistenceImplSupport.isDeleted((BaseGenericIdEntity) entity, changeListener)) {
type = EntityChangedEvent.Type.DELETED;
attributeChanges = getEntityAttributeChanges(entity, true);
} else if (info.onUpdated && changeListener.hasChanges()) {
type = EntityChangedEvent.Type.UPDATED;
attributeChanges = getEntityAttributeChanges(entity, changeListener.getObjectChangeSet());
}
}
}
if (type != null) {
@SuppressWarnings("unchecked") EntityChangedEventInfo eventData = new EntityChangedEventInfo(this, entity, type, attributeChanges);
list.add(eventData);
}
}
}
log.trace("collected {}", list);
return list;
}
use of com.haulmont.cuba.core.app.events.EntityChangedEvent in project documentation by cuba-platform.
the class OrderLineChangedListener method beforeCommit.
@EventListener
public void beforeCommit(EntityChangedEvent<OrderLine, UUID> event) {
Order order;
if (event.getType() != EntityChangedEvent.Type.DELETED) {
// <1>
order = // <2>
txDm.load(event.getEntityId()).view(// <3>
"orderLine-with-order").one().getOrder();
} else {
// <5>
Id<Order, UUID> orderId = event.getChanges().getOldReferenceId("order");
order = txDm.load(orderId).one();
}
long count = // <6>
txDm.load(OrderLine.class).query("select o from sales_OrderLine o where o.order = :order").parameter("order", order).view("orderLine-with-product").list().stream().filter(orderLine -> Boolean.TRUE.equals(orderLine.getProduct().getSpecial())).count();
order.setNumberOfSpecialProducts((int) count);
// <7>
txDm.save(order);
}
use of com.haulmont.cuba.core.app.events.EntityChangedEvent in project jmix by jmix-framework.
the class CubaEntityChangedEventManager method handleEvent.
@EventListener
public void handleEvent(io.jmix.core.event.EntityChangedEvent<? extends Entity> event) {
PublishingInfo info = infoCache.computeIfAbsent(event.getEntityId().getEntityClass(), aClass -> {
MetaClass metaClass = metadata.getClass(event.getEntityId().getEntityClass());
MetaClass originalMetaClass = extendedEntities.getOriginalOrThisMetaClass(metaClass);
Map attrMap = (Map) metaClass.getAnnotations().get(PublishEntityChangedEvents.class.getName());
if (attrMap != null) {
return new PublishingInfo(Boolean.TRUE.equals(attrMap.get("created")), Boolean.TRUE.equals(attrMap.get("updated")), Boolean.TRUE.equals(attrMap.get("deleted")), originalMetaClass);
}
return new PublishingInfo();
});
EntityChangedEvent.Type type = resolveType(event.getType());
if (!info.publish || (!info.onCreated && type == EntityChangedEvent.Type.CREATED) || (!info.onUpdated && type == EntityChangedEvent.Type.UPDATED) || (!info.onDeleted && type == EntityChangedEvent.Type.DELETED)) {
return;
}
io.jmix.core.Id<? extends Entity> entityId = event.getEntityId();
eventPublisher.publish(new EntityChangedEvent<>(event.getSource(), Id.of(entityId.getValue(), entityId.getEntityClass()), type, new AttributeChanges(event.getChanges())));
}
use of com.haulmont.cuba.core.app.events.EntityChangedEvent in project documentation by cuba-platform.
the class CustomerChangedListener method beforeCommit.
// <1>
@EventListener
public void beforeCommit(EntityChangedEvent<Customer, UUID> event) {
// <2>
Id<Customer, UUID> entityId = event.getEntityId();
// <3>
EntityChangedEvent.Type changeType = event.getType();
AttributeChanges changes = event.getChanges();
if (changes.isChanged("name")) {
// <4>
// <5>
String oldName = changes.getOldValue("name");
// ...
}
}
Aggregations