private void addCollectionChangeWorkUnit(AuditProcess auditProcess, ISessionImplementor session, string fromEntityName, RelationDescription relDesc, object value) { // relDesc.getToEntityName() doesn't always return the entity name of the value - in case // of subclasses, this will be root class, no the actual class. So it can't be used here. string toEntityName; object id; if (value is INHibernateProxy newValueAsProxy) { toEntityName = session.BestGuessEntityName(value); id = newValueAsProxy.HibernateLazyInitializer.Identifier; // We've got to initialize the object from the proxy to later read its state. value = Toolz.GetTargetFromProxy(session, newValueAsProxy); } else { toEntityName = session.GuessEntityName(value); var idMapper = VerCfg.EntCfg[toEntityName].IdMapper; id = idMapper.MapToIdFromEntity(value); } var toPropertyNames = VerCfg.EntCfg.ToPropertyNames(fromEntityName, relDesc.FromPropertyName, toEntityName); var toPropertyName = toPropertyNames.First(); auditProcess.AddWorkUnit(new CollectionChangeWorkUnit(session, toEntityName, toPropertyName, VerCfg, id, value)); }
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)); }
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)); } } }