Search in sources :

Example 1 with PersistentCollectionChangeData

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);
    }
}
Also used : HashMap(java.util.HashMap) PersistentCollectionChangeData(org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData)

Example 2 with PersistentCollectionChangeData

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.");
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) PersistentCollectionChangeData(org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData)

Example 3 with PersistentCollectionChangeData

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));
        }
    }
}
Also used : Serializable(java.io.Serializable) IdMapper(org.hibernate.envers.internal.entities.mapper.id.IdMapper) PersistentCollectionChangeData(org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData) CollectionChangeWorkUnit(org.hibernate.envers.internal.synchronization.work.CollectionChangeWorkUnit) PersistentCollectionChangeWorkUnit(org.hibernate.envers.internal.synchronization.work.PersistentCollectionChangeWorkUnit)

Example 4 with PersistentCollectionChangeData

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()));
}
Also used : Serializable(java.io.Serializable) RevisionType(org.hibernate.envers.RevisionType) IdMapper(org.hibernate.envers.internal.entities.mapper.id.IdMapper) AuditWorkUnit(org.hibernate.envers.internal.synchronization.work.AuditWorkUnit) FakeBidirectionalRelationWorkUnit(org.hibernate.envers.internal.synchronization.work.FakeBidirectionalRelationWorkUnit) PersistentCollectionChangeData(org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData) CollectionChangeWorkUnit(org.hibernate.envers.internal.synchronization.work.CollectionChangeWorkUnit) PersistentCollectionChangeWorkUnit(org.hibernate.envers.internal.synchronization.work.PersistentCollectionChangeWorkUnit)

Example 5 with PersistentCollectionChangeData

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);
    }
}
Also used : AuditEntitiesConfiguration(org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration) PersistentCollectionChangeData(org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

PersistentCollectionChangeData (org.hibernate.envers.internal.entities.mapper.PersistentCollectionChangeData)7 ArrayList (java.util.ArrayList)3 HashMap (java.util.HashMap)3 Serializable (java.io.Serializable)2 Collection (java.util.Collection)2 PersistentCollection (org.hibernate.collection.spi.PersistentCollection)2 IdMapper (org.hibernate.envers.internal.entities.mapper.id.IdMapper)2 CollectionChangeWorkUnit (org.hibernate.envers.internal.synchronization.work.CollectionChangeWorkUnit)2 PersistentCollectionChangeWorkUnit (org.hibernate.envers.internal.synchronization.work.PersistentCollectionChangeWorkUnit)2 HashSet (java.util.HashSet)1 Iterator (java.util.Iterator)1 Map (java.util.Map)1 RevisionType (org.hibernate.envers.RevisionType)1 AuditEntitiesConfiguration (org.hibernate.envers.configuration.internal.AuditEntitiesConfiguration)1 AuditWorkUnit (org.hibernate.envers.internal.synchronization.work.AuditWorkUnit)1 FakeBidirectionalRelationWorkUnit (org.hibernate.envers.internal.synchronization.work.FakeBidirectionalRelationWorkUnit)1