internal static DynamicUpdateMap Merge(DynamicUpdateMap first, DynamicUpdateMap second, MergeErrorContext errorContext) { if (first == null || second == null) { return(first ?? second); } if (first.IsNoChanges || second.IsNoChanges) { // DynamicUpdateMap.NoChanges has zero members, so we need to special-case it here. return(first.IsNoChanges ? second : first); } ThrowIfMapsIncompatible(first, second, errorContext); DynamicUpdateMap result = new DynamicUpdateMap { IsForImplementation = first.IsForImplementation, NewDefinitionMemberCount = second.NewDefinitionMemberCount, ArgumentsAreUnknown = first.ArgumentsAreUnknown && second.ArgumentsAreUnknown, oldArguments = first.ArgumentsAreUnknown ? second.oldArguments : first.oldArguments, newArguments = second.ArgumentsAreUnknown ? first.newArguments : second.newArguments }; foreach (DynamicUpdateMapEntry firstEntry in first.Entries) { DynamicUpdateMapEntry parent = null; if (firstEntry.Parent != null) { result.TryGetUpdateEntry(firstEntry.Parent.OldActivityId, out parent); } if (firstEntry.IsRemoval) { result.AddEntry(firstEntry.Clone(parent)); } else { DynamicUpdateMapEntry secondEntry = second.entries[firstEntry.NewActivityId]; result.AddEntry(DynamicUpdateMapEntry.Merge(firstEntry, secondEntry, parent, errorContext)); } } return(result); }
// rootIdSpace is optional. if it's null, result.NewActivity will be null internal UpdatedActivity GetUpdatedActivity(QualifiedId oldQualifiedId, IdSpace rootIdSpace) { UpdatedActivity result = new UpdatedActivity(); int[] oldIdSegments = oldQualifiedId.AsIDArray(); int[] newIdSegments = null; IdSpace currentIdSpace = rootIdSpace; DynamicUpdateMap currentMap = this; Fx.Assert(!this.IsForImplementation, "This method is never supposed to be called on an implementation map."); for (int i = 0; i < oldIdSegments.Length; i++) { if (currentMap == null || currentMap.Entries.Count == 0) { break; } DynamicUpdateMapEntry entry; if (!currentMap.TryGetUpdateEntry(oldIdSegments[i], out entry)) { // UpdateMap should contain entries for all old activities in the IdSpace int[] subIdSegments = new int[i + 1]; Array.Copy(oldIdSegments, subIdSegments, subIdSegments.Length); throw FxTrace.Exception.AsError(new InstanceUpdateException(SR.InvalidUpdateMap( SR.MapEntryNotFound(new QualifiedId(subIdSegments))))); } if (entry.IsIdChange) { if (newIdSegments == null) { newIdSegments = new int[oldIdSegments.Length]; Array.Copy(oldIdSegments, newIdSegments, oldIdSegments.Length); } newIdSegments[i] = entry.NewActivityId; } Activity currentActivity = null; if (currentIdSpace != null && !entry.IsRemoval) { currentActivity = currentIdSpace[entry.NewActivityId]; if (currentActivity == null) { // New Activity pointed to by UpdateMap should exist string activityId = currentIdSpace.Owner.Id + "." + entry.NewActivityId.ToString(CultureInfo.InvariantCulture); throw FxTrace.Exception.AsError(new InstanceUpdateException(SR.InvalidUpdateMap( SR.ActivityNotFound(activityId)))); } currentIdSpace = currentActivity.ParentOf; } if (i == oldIdSegments.Length - 1) { result.Map = currentMap; result.MapEntry = entry; result.NewActivity = currentActivity; } else if (entry.IsRuntimeUpdateBlocked || entry.IsUpdateBlockedByUpdateAuthor) { currentMap = null; } else { currentMap = entry.ImplementationUpdateMap; } } result.IdChanged = newIdSegments != null; result.NewId = result.IdChanged ? new QualifiedId(newIdSegments) : oldQualifiedId; return(result); }