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;
        }
        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);
            }
        }
Example #3
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;

            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 = VerCfg.EntCfg[entityName].GetRelationDescription(referencingPropertyName);
            if (rd != null && 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(),
                                                                VerCfg, evt.AffectedOwnerIdOrNull, evt.AffectedOwnerOrNull));

                    GenerateBidirectionalCollectionChangeWorkUnits(verSync, evt, workUnit, rd);
                }
            }
        }
Example #4
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(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, 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, VerCfg,
                    evt.AffectedOwnerIdOrNull, evt.AffectedOwnerOrNull));
        }
Example #5
0
 private static CollectionEntry GetCollectionEntry(AbstractCollectionEvent evt)
 {
     return evt.Session.PersistenceContext.GetCollectionEntry(evt.Collection);
 }
		public void AddEvent(AbstractCollectionEvent @event, IListener listener)
		{
			listenersCalled.Add(listener);
			events.Add(@event);
		}
			public void AddEvent(AbstractCollectionEvent @event, IListener listener)
			{
				listeners.AddEvent(@event, listener);
			}
        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));
                }
            }
        }