예제 #1
0
        private bool shouldGenerateRevision(AbstractCollectionEvent evt)
        {
            var entityName = evt.GetAffectedOwnerEntityName();

            return(VerCfg.GlobalCfg.GenerateRevisionsForCollections &&
                   VerCfg.EntCfg.IsVersioned(entityName));
        }
예제 #2
0
        void OnCollection(AbstractCollectionEvent e)
        {
            var affected = e.AffectedOwnerOrNull as IModifyAuditable <T>;

            if (affected == null)
            {
                return;
            }

            affected.ModifiedBy = GetEntity(e.Session);
            affected.ModifiedAt = DateTime.Now;
        }
예제 #3
0
        private object GetId(object entity, AbstractCollectionEvent @event)
        {
            object id = @event.AffectedOwnerIdOrNull;

            if (id == null)
            {
                // most likely this recovery is unnecessary since Hibernate Core probably try that
                EntityEntry entityEntry = (EntityEntry)@event.Session.PersistenceContext.EntityEntries[entity];
                id = entityEntry == null ? null : entityEntry.Id;
            }

            return(id);
        }
예제 #4
0
        private void onCollectionAction(AbstractCollectionEvent evt,
                                        IPersistentCollection newColl,
                                        object oldColl,
                                        CollectionEntry collectionEntry)
        {
            if (!VerCfg.GlobalCfg.GenerateRevisionsForCollections)
            {
                return;
            }
            var entityName = evt.GetAffectedOwnerEntityName();

            if (!VerCfg.EntCfg.IsVersioned(entityName))
            {
                return;
            }
            checkIfTransactionInProgress(evt.Session);

            var verSync                 = VerCfg.AuditProcessManager.Get(evt.Session);
            var ownerEntityName         = ((AbstractCollectionPersister)collectionEntry.LoadedPersister).OwnerEntityName;
            var referencingPropertyName = collectionEntry.Role.Substring(ownerEntityName.Length + 1);

            // Checking if this is not a "fake" many-to-one bidirectional relation. The relation description may be
            // null in case of collections of non-entities.
            var rd = getRelationDescriptionWithInheritedRelations(entityName, referencingPropertyName);

            if (rd?.MappedByPropertyName != null)
            {
                generateFakeBidirecationalRelationWorkUnits(verSync, newColl, oldColl, entityName,
                                                            referencingPropertyName, evt, rd);
            }
            else
            {
                var workUnit = new PersistentCollectionChangeWorkUnit(evt.Session, entityName, VerCfg, newColl,
                                                                      collectionEntry, oldColl, evt.AffectedOwnerIdOrNull,
                                                                      referencingPropertyName);
                verSync.AddWorkUnit(workUnit);

                if (workUnit.ContainsWork())
                {
                    // There are some changes: a revision needs also be generated for the collection owner
                    verSync.AddWorkUnit(new CollectionChangeWorkUnit(evt.Session, evt.GetAffectedOwnerEntityName(), referencingPropertyName,
                                                                     VerCfg, evt.AffectedOwnerIdOrNull, evt.AffectedOwnerOrNull));

                    generateBidirectionalCollectionChangeWorkUnits(verSync, evt, workUnit, rd);
                }
            }
        }
예제 #5
0
        private void generateFakeBidirecationalRelationWorkUnits(AuditProcess auditProcess,
                                                                 IPersistentCollection newColl,
                                                                 object oldColl,
                                                                 string collectionEntityName,
                                                                 string referencingPropertyName,
                                                                 AbstractCollectionEvent evt,
                                                                 RelationDescription rd)
        {
            // First computing the relation changes
            var collectionChanges = VerCfg.EntCfg[collectionEntityName].PropertyMapper
                                    .MapCollectionChanges(evt.Session, referencingPropertyName, newColl, oldColl, evt.AffectedOwnerIdOrNull);

            // Getting the id mapper for the related entity, as the work units generated will corrspond to the related
            // entities.
            var relatedEntityName = rd.ToEntityName;
            var relatedIdMapper   = VerCfg.EntCfg[relatedEntityName].IdMapper;

            // For each collection change, generating the bidirectional work unit.
            foreach (var changeData in collectionChanges)
            {
                var relatedObj = changeData.GetChangedElement();
                var relatedId  = relatedIdMapper.MapToIdFromEntity(relatedObj);
                var revType    = (RevisionType)changeData.Data[VerCfg.AuditEntCfg.RevisionTypePropName];

                // This can be different from relatedEntityName, in case of inheritance (the real entity may be a subclass
                // of relatedEntityName).
                var realRelatedEntityName = evt.Session.BestGuessEntityName(relatedObj);

                // By default, the nested work unit is a collection change work unit.
                var nestedWorkUnit = new CollectionChangeWorkUnit(evt.Session, realRelatedEntityName, rd.MappedByPropertyName, VerCfg,
                                                                  relatedId, relatedObj);

                auditProcess.AddWorkUnit(new FakeBidirectionalRelationWorkUnit(evt.Session, realRelatedEntityName, VerCfg,
                                                                               relatedId, referencingPropertyName, evt.AffectedOwnerOrNull, rd, revType,
                                                                               changeData.GetChangedElementIndex(), nestedWorkUnit));
            }

            // We also have to generate a collection change work unit for the owning entity.
            auditProcess.AddWorkUnit(new CollectionChangeWorkUnit(evt.Session, collectionEntityName, referencingPropertyName, VerCfg,
                                                                  evt.AffectedOwnerIdOrNull, evt.AffectedOwnerOrNull));
        }
예제 #6
0
        private void OnCollectionAction(AbstractCollectionEvent evt, IPersistentCollection newColl, object oldColl,
                                        CollectionEntry collectionEntry)
        {
            String entityName = evt.GetAffectedOwnerEntityName();

            if (verCfg.EntCfg.IsVersioned(entityName))
            {
                AuditSync verSync = verCfg.AuditSyncManager.get(evt.Session);

                String ownerEntityName         = ((AbstractCollectionPersister)collectionEntry.LoadedPersister).OwnerEntityName;
                String referencingPropertyName = collectionEntry.Role.Substring(ownerEntityName.Length + 1);

                // Checking if this is not a "fake" many-to-one bidirectional relation. The relation description may be
                // null in case of collections of non-entities.
                RelationDescription rd = verCfg.EntCfg[entityName].GetRelationDescription(referencingPropertyName);
                if (rd != null && rd.MappedByPropertyName != null)
                {
                    GenerateFakeBidirecationalRelationWorkUnits(verSync, newColl, oldColl, entityName,
                                                                referencingPropertyName, evt, rd);
                }
                else
                {
                    PersistentCollectionChangeWorkUnit workUnit = new PersistentCollectionChangeWorkUnit(evt.Session,
                                                                                                         entityName, verCfg, newColl, collectionEntry, oldColl, evt.AffectedOwnerIdOrNull,
                                                                                                         referencingPropertyName);
                    verSync.AddWorkUnit(workUnit);

                    if (workUnit.ContainsWork())
                    {
                        // There are some changes: a revision needs also be generated for the collection owner
                        verSync.AddWorkUnit(new CollectionChangeWorkUnit(evt.Session, evt.GetAffectedOwnerEntityName(),
                                                                         verCfg, evt.AffectedOwnerIdOrNull, evt.AffectedOwnerOrNull));

                        GenerateBidirectionalCollectionChangeWorkUnits(verSync, evt, workUnit, rd);
                    }
                }
            }
        }
예제 #7
0
        private void generateBidirectionalCollectionChangeWorkUnits(AuditProcess auditProcess,
                                                                    AbstractCollectionEvent evt,
                                                                    PersistentCollectionChangeWorkUnit workUnit,
                                                                    RelationDescription rd)
        {
            // Checking if this is enabled in configuration ...
            if (!VerCfg.GlobalCfg.GenerateRevisionsForCollections)
            {
                return;
            }

            // Checking if this is not a bidirectional relation - then, a revision needs also be generated for
            // the other side of the relation.
            // relDesc can be null if this is a collection of simple values (not a relation).
            if (rd != null && rd.Bidirectional)
            {
                var relatedEntityName = rd.ToEntityName;
                var relatedIdMapper   = VerCfg.EntCfg[relatedEntityName].IdMapper;

                foreach (var changeData in workUnit.CollectionChanges)
                {
                    var relatedObj = changeData.GetChangedElement();
                    var relatedId  = relatedIdMapper.MapToIdFromEntity(relatedObj);

                    var toPropertyNames = VerCfg.EntCfg.ToPropertyNames(evt.GetAffectedOwnerEntityName(), rd.FromPropertyName, relatedEntityName);
                    var toPropertyName  = toPropertyNames.First();

                    auditProcess.AddWorkUnit(new CollectionChangeWorkUnit(evt.Session,
                                                                          evt.Session.BestGuessEntityName(relatedObj),
                                                                          toPropertyName,
                                                                          VerCfg,
                                                                          relatedId,
                                                                          relatedObj));
                }
            }
        }
예제 #8
0
        private void ProcessCollectionEvent(AbstractCollectionEvent @event)
        {
            object entity = @event.AffectedOwnerOrNull;

            if (entity == null)
            {
                // Hibernate cannot determine every single time the owner especially incase detached objects are involved
                // or property-ref is used
                // Should log really but we don't know if we're interested in this collection for indexing
                return;
            }

            if (used && EntityIsIndexed(entity))
            {
                object id = GetId(entity, @event);
                if (id == null)
                {
                    log.Warn("Unable to reindex entity on collection change, id cannot be extracted: " + @event.GetAffectedOwnerEntityName());
                    return;
                }

                ProcessWork(entity, id, WorkType.Collection, @event);
            }
        }
예제 #9
0
 public void AddEvent(AbstractCollectionEvent @event, IListener listener)
 {
     listenersCalled.Add(listener);
     events.Add(@event);
 }
예제 #10
0
 public void AddEvent(AbstractCollectionEvent @event, IListener listener)
 {
     listeners.AddEvent(@event, listener);
 }
예제 #11
0
 private static object initializeCollection(AbstractCollectionEvent evt)
 {
     evt.Collection.ForceInitialization();
     return(evt.Collection.StoredSnapshot);
 }
예제 #12
0
 private static CollectionEntry getCollectionEntry(AbstractCollectionEvent evt)
 {
     return(evt.Session.PersistenceContext.GetCollectionEntry(evt.Collection));
 }
예제 #13
0
        private void GenerateBidirectionalCollectionChangeWorkUnits(AuditSync verSync, AbstractCollectionEvent evt,
                                                                    PersistentCollectionChangeWorkUnit workUnit,
                                                                    RelationDescription rd)
        {
            // Checking if this is enabled in configuration ...
            if (!verCfg.GlobalCfg.isGenerateRevisionsForCollections())
            {
                return;
            }

            // Checking if this is not a bidirectional relation - then, a revision needs also be generated for
            // the other side of the relation.
            // relDesc can be null if this is a collection of simple values (not a relation).
            if (rd != null && rd.Bidirectional)
            {
                String    relatedEntityName = rd.ToEntityName;
                IIdMapper relatedIdMapper   = verCfg.EntCfg[relatedEntityName].GetIdMapper();

                foreach (PersistentCollectionChangeData changeData in workUnit.getCollectionChanges())
                {
                    Object relatedObj = changeData.GetChangedElement();
                    object relatedId  = relatedIdMapper.MapToIdFromEntity(relatedObj);

                    verSync.AddWorkUnit(new CollectionChangeWorkUnit(evt.Session, relatedEntityName, verCfg,
                                                                     relatedId, relatedObj));
                }
            }
        }