// For most of the time, we need source location for object that appear on XAML. // During debugging, however, we must not transform the internal activity to their origin to make sure it stop when the internal activity is about the execute // Therefore, in debugger scenario, translateInternalActivityToOrigin will be set to false. internal static Dictionary <object, SourceLocation> GetSourceLocations(Activity rootActivity, WorkflowSymbol symbol, bool translateInternalActivityToOrigin) { Activity workflowRoot = rootActivity.RootActivity ?? rootActivity; if (!workflowRoot.IsMetadataFullyCached) { IList <ValidationError> validationErrors = null; ActivityUtilities.CacheRootMetadata(workflowRoot, new ActivityLocationReferenceEnvironment(), ProcessActivityTreeOptions.ValidationOptions, null, ref validationErrors); } Dictionary <object, SourceLocation> newMapping = new Dictionary <object, SourceLocation>(); // Make sure the qid we are using to TryGetElementFromRoot // are shifted appropriately such that the first digit that QID is // the same as the last digit of the rootActivity.QualifiedId. int[] rootIdArray = rootActivity.QualifiedId.AsIDArray(); int idOffset = rootIdArray[rootIdArray.Length - 1] - 1; foreach (ActivitySymbol actSym in symbol.Symbols) { QualifiedId qid = new QualifiedId(actSym.QualifiedId); if (idOffset != 0) { int[] idArray = qid.AsIDArray(); idArray[0] += idOffset; qid = new QualifiedId(idArray); } Activity activity; if (QualifiedId.TryGetElementFromRoot(rootActivity, qid, out activity)) { object origin = activity; if (translateInternalActivityToOrigin && activity.Origin != null) { origin = activity.Origin; } newMapping.Add(origin, new SourceLocation(symbol.FileName, symbol.GetChecksum(), actSym.StartLine, actSym.StartColumn, actSym.EndLine, actSym.EndColumn)); } } return(newMapping); }
// 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); }
// targetDefinition argument is optional. private IList <InstanceListNeedingUpdate> GetInstanceListsNeedingUpdate(DynamicUpdateMap updateMap, Activity targetDefinition, List <ActivityInstance> secondaryRootInstances, ref Collection <ActivityBlockingUpdate> updateErrors) { IList <InstanceListNeedingUpdate> instanceListsToUpdate = new List <InstanceListNeedingUpdate>(); if (this.rawDeserializedLists == null) { // This instance doesn't have any active instances (it is complete). return(instanceListsToUpdate); } IdSpace rootIdSpace = null; if (targetDefinition != null) { rootIdSpace = targetDefinition.MemberOf; } for (int i = 0; i < this.rawDeserializedLists.Length; i++) { InstanceList list = this.rawDeserializedLists[i]; QualifiedId oldQualifiedId = new QualifiedId(list.ActivityId); if (updateMap.IsImplementationAsRoot) { int[] oldIdArray = oldQualifiedId.AsIDArray(); if (oldIdArray.Length == 1 && oldIdArray[0] != 1) { throw FxTrace.Exception.AsError(new InstanceUpdateException(SR.InvalidImplementationAsWorkflowRootForRuntimeState)); } } string error; InstanceListNeedingUpdate update; DynamicUpdateMap.UpdatedActivity updatedActivity = updateMap.GetUpdatedActivity(oldQualifiedId, rootIdSpace); if (CanCompensationOrConfirmationHandlerReferenceAddedSymbols(list, updateMap, rootIdSpace, secondaryRootInstances, ref updateErrors)) { update = null; } else if (updatedActivity.MapEntry == null) { if (updatedActivity.IdChanged) { // this newQualifiedId is the new id for those InstanceLists whose IDs shifted by their parents' ID change update = new InstanceListNeedingUpdate { InstanceList = list, NewId = updatedActivity.NewId }; } else { // nothing changed, no map, no mapEntry update = new InstanceListNeedingUpdate { InstanceList = list, NewId = null, }; } } else if (updatedActivity.MapEntry.IsParentRemovedOrBlocked) { update = null; } else if (IsRemovalOrRTUpdateBlockedOrBlockedByUser(updatedActivity, oldQualifiedId, out error)) { string instanceId = null; for (int j = 0; j < list.Count; j++) { ActivityInstance activityInstance = list[j] as ActivityInstance; if (activityInstance != null) { instanceId = activityInstance.Id; break; } } AddBlockingActivity(ref updateErrors, updatedActivity, oldQualifiedId, error, instanceId); update = null; } else if (IsInvalidEnvironmentUpdate(list, updatedActivity, ref updateErrors)) { update = null; } else { // no validation error for this InstanceList // add it to the list of InstanceLists to be updated update = new InstanceListNeedingUpdate { InstanceList = list, NewId = updatedActivity.NewId, UpdateMap = updatedActivity.Map, MapEntry = updatedActivity.MapEntry, NewActivity = updatedActivity.NewActivity }; } if (update != null) { update.OriginalId = list.ActivityId; instanceListsToUpdate.Add(update); } } return(instanceListsToUpdate); }
// For most of the time, we need source location for object that appear on XAML. // During debugging, however, we must not transform the internal activity to their origin to make sure it stop when the internal activity is about the execute // Therefore, in debugger scenario, translateInternalActivityToOrigin will be set to false. internal static Dictionary<object, SourceLocation> GetSourceLocations(Activity rootActivity, WorkflowSymbol symbol, bool translateInternalActivityToOrigin) { Activity workflowRoot = rootActivity.RootActivity ?? rootActivity; if (!workflowRoot.IsMetadataFullyCached) { IList<ValidationError> validationErrors = null; ActivityUtilities.CacheRootMetadata(workflowRoot, new ActivityLocationReferenceEnvironment(), ProcessActivityTreeOptions.ValidationOptions, null, ref validationErrors); } Dictionary<object, SourceLocation> newMapping = new Dictionary<object, SourceLocation>(); // Make sure the qid we are using to TryGetElementFromRoot // are shifted appropriately such that the first digit that QID is // the same as the last digit of the rootActivity.QualifiedId. int[] rootIdArray = rootActivity.QualifiedId.AsIDArray(); int idOffset = rootIdArray[rootIdArray.Length - 1] - 1; foreach (ActivitySymbol actSym in symbol.Symbols) { QualifiedId qid = new QualifiedId(actSym.QualifiedId); if (idOffset != 0) { int[] idArray = qid.AsIDArray(); idArray[0] += idOffset; qid = new QualifiedId(idArray); } Activity activity; if (QualifiedId.TryGetElementFromRoot(rootActivity, qid, out activity)) { object origin = activity; if (translateInternalActivityToOrigin && activity.Origin != null) { origin = activity.Origin; } newMapping.Add(origin, new SourceLocation(symbol.FileName, symbol.GetChecksum(), actSym.StartLine, actSym.StartColumn, actSym.EndLine, actSym.EndColumn)); } } return newMapping; }