public IList <IEntityMetaData> GetMetaData(IList <Type> entityTypes) { IdentityHashMap <IMergeServiceExtension, IList <Type> > mseToEntityTypes = new IdentityHashMap <IMergeServiceExtension, IList <Type> >(); for (int a = entityTypes.Count; a-- > 0;) { Type entityType = entityTypes[a]; IMergeServiceExtension mergeServiceExtension = mergeServiceExtensions.GetExtension(entityType); if (mergeServiceExtension == null) { continue; } IList <Type> groupedEntityTypes = mseToEntityTypes.Get(mergeServiceExtension); if (groupedEntityTypes == null) { groupedEntityTypes = new List <Type>(); mseToEntityTypes.Put(mergeServiceExtension, groupedEntityTypes); } groupedEntityTypes.Add(entityType); } List <IEntityMetaData> metaDataResult = new List <IEntityMetaData>(entityTypes.Count); foreach (Entry <IMergeServiceExtension, IList <Type> > entry in mseToEntityTypes) { IList <IEntityMetaData> groupedMetaData = entry.Key.GetMetaData(entry.Value); metaDataResult.AddRange(groupedMetaData); } return(metaDataResult); }
protected IMergeServiceExtension GetServiceForType(Type type) { if (type == null) { return(null); } IMergeServiceExtension mse = mergeServiceExtensions.GetExtension(type); if (mse == null) { throw new Exception("No merge service found to handle entity type '" + type.FullName + "'"); } return(mse); }
protected ICUDResult WhatIfMerged(ICUDResult cudResult, IMethodDescription methodDescription, List <MergeOperation> mergeOperationSequence, IncrementalMergeState incrementalState) { IList <MergeOperation> lastMergeOperationSequence; while (true) { IMap <Type, IList <IChangeContainer> > sortedChanges = BucketSortChanges(cudResult.AllChanges); lastMergeOperationSequence = CreateMergeOperationSequence(sortedChanges); ParamHolder <bool> hasAtLeastOneImplicitChange = new ParamHolder <bool>(false); IList <MergeOperation> fLastMergeOperationSequence = lastMergeOperationSequence; cudResult = CacheContext.ExecuteWithCache(incrementalState.GetStateCache(), delegate(ICUDResult cudResult2) { for (int a = 0, size = fLastMergeOperationSequence.Count; a < size; a++) { MergeOperation mergeOperation = fLastMergeOperationSequence[a]; IMergeServiceExtension mergeServiceExtension = mergeOperation.MergeServiceExtension; ICUDResult explAndImplCudResult = mergeServiceExtension.EvaluateImplicitChanges(cudResult2, incrementalState); cudResult2 = MergeCudResult(cudResult2, explAndImplCudResult, mergeServiceExtension, hasAtLeastOneImplicitChange, incrementalState); } return(cudResult2); }, cudResult); foreach (IMergeListener mergeListener in mergeListeners.GetExtensions()) { ICUDResult explAndImplCudResult = mergeListener.PreMerge(cudResult, incrementalState.GetStateCache()); cudResult = MergeCudResult(cudResult, explAndImplCudResult, mergeListener, hasAtLeastOneImplicitChange, incrementalState); } if (!hasAtLeastOneImplicitChange.Value) { break; } } mergeOperationSequence.AddRange(lastMergeOperationSequence); return(cudResult); }
public void UnregisterMergeServiceExtension(IMergeServiceExtension mergeServiceExtension, Type entityType) { mergeServiceExtensions.Unregister(mergeServiceExtension, entityType); }
protected IList <MergeOperation> CreateMergeOperationSequence(IMap <Type, IList <IChangeContainer> > sortedChanges) { Type[] entityPersistOrder = EntityMetaDataProvider.GetEntityPersistOrder(); IList <MergeOperation> mergeOperations = new List <MergeOperation>(); if (entityPersistOrder != null) { for (int a = entityPersistOrder.Length; a-- > 0;) { Type orderedEntityType = entityPersistOrder[a]; IList <IChangeContainer> changes = sortedChanges.Get(orderedEntityType); if (changes == null) { // No changes of current type found. Nothing to do here continue; } List <IChangeContainer> removes = new List <IChangeContainer>(changes.Count); List <IChangeContainer> insertsAndUpdates = new List <IChangeContainer>(changes.Count); for (int b = changes.Count; b-- > 0;) { IChangeContainer change = changes[b]; if (change is DeleteContainer) { removes.Add(change); } else { insertsAndUpdates.Add(change); } } if (removes.Count == 0) { // Nothing to do. Ordering is not necessary here continue; } if (insertsAndUpdates.Count == 0) { sortedChanges.Remove(orderedEntityType); } else { sortedChanges.Put(orderedEntityType, insertsAndUpdates); } IMergeServiceExtension mergeServiceExtension = GetServiceForType(orderedEntityType); MergeOperation mergeOperation = new MergeOperation(); mergeOperation.MergeServiceExtension = mergeServiceExtension; mergeOperation.ChangeContainer = removes; mergeOperations.Add(mergeOperation); } for (int a = 0, size = entityPersistOrder.Length; a < size; a++) { Type orderedEntityType = entityPersistOrder[a]; IList <IChangeContainer> changes = sortedChanges.Get(orderedEntityType); if (changes == null) { // No changes of current type found. Nothing to do here continue; } bool containsNew = false; for (int b = changes.Count; b-- > 0;) { if (changes[b].Reference.Id == null) { containsNew = true; break; } } if (!containsNew) { // Nothing to do. Ordering is not necessary here continue; } // Remove batch of changes where at least 1 new entity occured and // this type of entity has to be inserted in a global order sortedChanges.Remove(orderedEntityType); IMergeServiceExtension mergeServiceExtension = GetServiceForType(orderedEntityType); MergeOperation mergeOperation = new MergeOperation(); mergeOperation.MergeServiceExtension = mergeServiceExtension; mergeOperation.ChangeContainer = changes; mergeOperations.Add(mergeOperation); } } // Everything which is left in the sortedChanges map can be merged without global order, so batch together as much as possible foreach (Entry <Type, IList <IChangeContainer> > entry in sortedChanges) { Type type = entry.Key; IList <IChangeContainer> unorderedChanges = entry.Value; IMergeServiceExtension mergeServiceExtension = GetServiceForType(type); if (mergeServiceExtension == null) { throw new Exception("No extension found to merge entities of type '" + type.FullName + "'"); } bool cont = false; foreach (MergeOperation existingMergeOperation in mergeOperations) { if (Object.ReferenceEquals(existingMergeOperation.MergeServiceExtension, mergeServiceExtension)) { IList <IChangeContainer> orderedChanges = existingMergeOperation.ChangeContainer; for (int b = unorderedChanges.Count; b-- > 0;) { orderedChanges.Add(unorderedChanges[b]); } cont = true; break; } } if (cont) { continue; } MergeOperation mergeOperation = new MergeOperation(); mergeOperation.MergeServiceExtension = mergeServiceExtension; mergeOperation.ChangeContainer = unorderedChanges; mergeOperations.Add(mergeOperation); } ; return(mergeOperations); }
protected IOriCollection Intern(ICUDResult cudResult, IMethodDescription methodDescription, IList <MergeOperation> mergeOperationSequence, IncrementalMergeState state) { IList <IChangeContainer> allChanges = cudResult.AllChanges; IList <Object> originalRefs = cudResult.GetOriginalRefs(); IdentityHashMap <IChangeContainer, int> changeToChangeIndexDict = new IdentityHashMap <IChangeContainer, int>(); for (int a = allChanges.Count; a-- > 0;) { changeToChangeIndexDict.Put(allChanges[a], a); } IObjRef[] objRefs = new IObjRef[allChanges.Count]; long[] allChangedOn = new long[allChanges.Count]; String[] allChangedBy = new String[allChanges.Count]; CHashSet <long> changedOnSet = new CHashSet <long>(); CHashSet <String> changedBySet = new CHashSet <String>(); for (int a = 0, size = mergeOperationSequence.Count; a < size; a++) { MergeOperation mergeOperation = mergeOperationSequence[a]; IMergeServiceExtension mergeServiceExtension = mergeOperation.MergeServiceExtension; IList <IChangeContainer> changesForMergeService = mergeOperation.ChangeContainer; ICUDResult msCudResult = BuildCUDResult(changesForMergeService, changeToChangeIndexDict, originalRefs); IOriCollection msOriCollection = mergeServiceExtension.Merge(msCudResult, methodDescription); MergeController.ApplyChangesToOriginals(msCudResult, msOriCollection, state.GetStateCache()); IList <IObjRef> allChangeORIs = msOriCollection.AllChangeORIs; long? msDefaultChangedOn = msOriCollection.ChangedOn; String msDefaultChangedBy = msOriCollection.ChangedBy; long[] msAllChangedOn = msOriCollection.AllChangedOn; String[] msAllChangedBy = msOriCollection.AllChangedBy; for (int b = changesForMergeService.Count; b-- > 0;) { int index = changeToChangeIndexDict.Get(changesForMergeService[b]); objRefs[index] = allChangeORIs[b]; if (msAllChangedOn != null) { long msChangedOn = msAllChangedOn[b]; allChangedOn[index] = msChangedOn; changedOnSet.Add(msChangedOn); } else { allChangedOn[index] = msDefaultChangedOn.Value; } if (msAllChangedBy != null) { String msChangedBy = msAllChangedBy[b]; allChangedBy[index] = msChangedBy; changedBySet.Add(msChangedBy); } else { allChangedBy[index] = msDefaultChangedBy; } } if (msDefaultChangedOn != null) { changedOnSet.Add(msDefaultChangedOn.Value); } if (msDefaultChangedBy != null) { changedBySet.Add(msDefaultChangedBy); } } OriCollection oriCollection = new OriCollection(); oriCollection.AllChangeORIs = new List <IObjRef>(objRefs); if (changedBySet.Count == 1) { Iterator <String> iter = changedBySet.Iterator(); iter.MoveNext(); oriCollection.ChangedBy = iter.Current; } else { oriCollection.AllChangedBy = allChangedBy; } if (changedOnSet.Count == 1) { Iterator <long> iter = changedOnSet.Iterator(); iter.MoveNext(); oriCollection.ChangedOn = iter.Current; } else { oriCollection.AllChangedOn = allChangedOn; } foreach (IMergeListener mergeListener in mergeListeners.GetExtensions()) { mergeListener.PostMerge(cudResult, objRefs); } if (originalRefs != null) { // Set each original ref to null in order to suppress a post-processing in a potentially calling IMergeProcess for (int a = originalRefs.Count; a-- > 0;) { originalRefs[a] = null; } } // TODO DCE must be fired HERE <--- return(oriCollection); }