use of org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData in project hibernate-orm by hibernate.
the class AbstractCollectionMapper method addCollectionChanges.
private void addCollectionChanges(SessionImplementor session, List<PersistentCollectionChangeData> collectionChanges, Set<Object> changed, RevisionType revisionType, Serializable id) {
int ordinal = 0;
for (Object changedObj : changed) {
final Map<String, Object> entityData = new HashMap<>();
final Map<String, Object> originalId = createIdMap(ordinal++);
entityData.put(commonCollectionMapperData.getVerEntCfg().getOriginalIdPropName(), originalId);
collectionChanges.add(new PersistentCollectionChangeData(commonCollectionMapperData.getVersionsMiddleEntityName(), entityData, changedObj));
// Mapping the collection owner's id.
commonCollectionMapperData.getReferencingIdData().getPrefixedMapper().mapToMapFromId(originalId, id);
// Mapping collection element and index (if present).
mapToMapFromObject(session, originalId, entityData, changedObj);
(revisionTypeInId ? originalId : entityData).put(commonCollectionMapperData.getVerEntCfg().getRevisionTypePropName(), revisionType);
}
}
use of org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData in project hibernate-orm by hibernate.
the class PersistentCollectionChangeWorkUnit method dispatch.
@Override
public AuditWorkUnit dispatch(WorkUnitMergeVisitor first) {
if (first instanceof PersistentCollectionChangeWorkUnit) {
final PersistentCollectionChangeWorkUnit original = (PersistentCollectionChangeWorkUnit) first;
// Merging the collection changes in both work units.
// First building a map from the ids of the collection-entry-entities from the "second" collection changes,
// to the PCCD objects. That way, we will be later able to check if an "original" collection change
// should be added, or if it is overshadowed by a new one.
final Map<Object, PersistentCollectionChangeData> newChangesIdMap = new HashMap<>();
for (PersistentCollectionChangeData persistentCollectionChangeData : getCollectionChanges()) {
newChangesIdMap.put(getOriginalId(persistentCollectionChangeData), persistentCollectionChangeData);
}
// This will be the list with the resulting (merged) changes.
final List<PersistentCollectionChangeData> mergedChanges = new ArrayList<>();
// Including only those original changes, which are not overshadowed by new ones.
for (PersistentCollectionChangeData originalCollectionChangeData : original.getCollectionChanges()) {
final Object originalOriginalId = getOriginalId(originalCollectionChangeData);
if (!newChangesIdMap.containsKey(originalOriginalId)) {
mergedChanges.add(originalCollectionChangeData);
} else {
// If the changes collide, checking if the first one isn't a DEL, and the second a subsequent ADD
// If so, removing the change alltogether.
final String revTypePropName = enversService.getAuditEntitiesConfiguration().getRevisionTypePropName();
if (RevisionType.ADD.equals(newChangesIdMap.get(originalOriginalId).getData().get(revTypePropName)) && RevisionType.DEL.equals(originalCollectionChangeData.getData().get(revTypePropName))) {
newChangesIdMap.remove(originalOriginalId);
}
}
}
// Finally adding all of the new changes to the end of the list (the map values may differ from
// getCollectionChanges() because of the last operation above).
mergedChanges.addAll(newChangesIdMap.values());
return new PersistentCollectionChangeWorkUnit(sessionImplementor, entityName, enversService, id, mergedChanges, referencingPropertyName);
} else {
throw new RuntimeException("Trying to merge a " + first + " with a PersitentCollectionChangeWorkUnit. " + "This is not really possible.");
}
}
use of org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData in project hibernate-orm by hibernate.
the class BaseEnversCollectionEventListener method generateBidirectionalCollectionChangeWorkUnits.
private void generateBidirectionalCollectionChangeWorkUnits(AuditProcess auditProcess, AbstractCollectionEvent event, PersistentCollectionChangeWorkUnit workUnit, RelationDescription rd) {
// Checking if this is enabled in configuration ...
if (!getEnversService().getGlobalConfiguration().isGenerateRevisionsForCollections()) {
return;
}
// relDesc can be null if this is a collection of simple values (not a relation).
if (rd != null && rd.isBidirectional()) {
final String relatedEntityName = rd.getToEntityName();
final IdMapper relatedIdMapper = getEnversService().getEntitiesConfigurations().get(relatedEntityName).getIdMapper();
final Set<String> toPropertyNames = getEnversService().getEntitiesConfigurations().getToPropertyNames(event.getAffectedOwnerEntityName(), rd.getFromPropertyName(), relatedEntityName);
final String toPropertyName = toPropertyNames.iterator().next();
for (PersistentCollectionChangeData changeData : workUnit.getCollectionChanges()) {
final Object relatedObj = changeData.getChangedElement();
final Serializable relatedId = (Serializable) relatedIdMapper.mapToIdFromEntity(relatedObj);
auditProcess.addWorkUnit(new CollectionChangeWorkUnit(event.getSession(), event.getSession().bestGuessEntityName(relatedObj), toPropertyName, getEnversService(), relatedId, relatedObj));
}
}
}
use of org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData in project hibernate-orm by hibernate.
the class BaseEnversCollectionEventListener method generateFakeBidirecationalRelationWorkUnits.
private void generateFakeBidirecationalRelationWorkUnits(AuditProcess auditProcess, PersistentCollection newColl, Serializable oldColl, String collectionEntityName, String referencingPropertyName, AbstractCollectionEvent event, RelationDescription rd) {
// First computing the relation changes
final List<PersistentCollectionChangeData> collectionChanges = getEnversService().getEntitiesConfigurations().get(collectionEntityName).getPropertyMapper().mapCollectionChanges(event.getSession(), referencingPropertyName, newColl, oldColl, event.getAffectedOwnerIdOrNull());
// Getting the id mapper for the related entity, as the work units generated will correspond to the related
// entities.
final String relatedEntityName = rd.getToEntityName();
final IdMapper relatedIdMapper = getEnversService().getEntitiesConfigurations().get(relatedEntityName).getIdMapper();
// For each collection change, generating the bidirectional work unit.
for (PersistentCollectionChangeData changeData : collectionChanges) {
final Object relatedObj = changeData.getChangedElement();
final Serializable relatedId = (Serializable) relatedIdMapper.mapToIdFromEntity(relatedObj);
final RevisionType revType = (RevisionType) changeData.getData().get(getEnversService().getAuditEntitiesConfiguration().getRevisionTypePropName());
// This can be different from relatedEntityName, in case of inheritance (the real entity may be a subclass
// of relatedEntityName).
final String realRelatedEntityName = event.getSession().bestGuessEntityName(relatedObj);
// By default, the nested work unit is a collection change work unit.
final AuditWorkUnit nestedWorkUnit = new CollectionChangeWorkUnit(event.getSession(), realRelatedEntityName, rd.getMappedByPropertyName(), getEnversService(), relatedId, relatedObj);
auditProcess.addWorkUnit(new FakeBidirectionalRelationWorkUnit(event.getSession(), realRelatedEntityName, getEnversService(), relatedId, referencingPropertyName, event.getAffectedOwnerOrNull(), rd, revType, changeData.getChangedElementIndex(), nestedWorkUnit));
}
// We also have to generate a collection change work unit for the owning entity.
auditProcess.addWorkUnit(new CollectionChangeWorkUnit(event.getSession(), collectionEntityName, referencingPropertyName, getEnversService(), event.getAffectedOwnerIdOrNull(), event.getAffectedOwnerOrNull()));
}
use of org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData in project hibernate-orm by hibernate.
the class PersistentCollectionChangeWorkUnit method perform.
@Override
@SuppressWarnings({ "unchecked" })
public void perform(Session session, Object revisionData) {
final AuditEntitiesConfiguration entitiesCfg = enversService.getAuditEntitiesConfiguration();
for (PersistentCollectionChangeData persistentCollectionChangeData : collectionChanges) {
// Setting the revision number
((Map<String, Object>) persistentCollectionChangeData.getData().get(entitiesCfg.getOriginalIdPropName())).put(entitiesCfg.getRevisionFieldName(), revisionData);
auditStrategy.performCollectionChange(session, getEntityName(), referencingPropertyName, enversService, persistentCollectionChangeData, revisionData);
}
}
Aggregations