use of com.haulmont.cuba.core.sys.persistence.EntityChangedEventInfo 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;
}
Aggregations