Beispiel #1
0
        private static bool ValidateDUInUnconditionalTransition(NativeActivityUpdateMapMetadata metadata, InternalTransition updatedTransition, InternalTransition originalTransition, out string errorMessage)
        {
            Fx.Assert(originalTransition.IsUnconditional, "Transition should be unconditional in the original definition.");
            Activity originalAction = originalTransition.TransitionDataList[0].Action;

            foreach (TransitionData transitionData in updatedTransition.TransitionDataList)
            {
                Activity updatedAction = transitionData.Action;
                Activity actionMatch = metadata.GetMatch(updatedAction);
                Activity conditionMatch = metadata.GetMatch(transitionData.Condition);

                if ((null == originalAction && null != actionMatch) ||
                    (null != originalAction && null != actionMatch && !object.ReferenceEquals(originalAction, actionMatch)))
                {
                    // Transition.Action is an activity moved from elsewhere within the InternalState
                    errorMessage = SR.MovingActivitiesInStateBlockDU;
                    return false;
                }
            }

            errorMessage = string.Empty;
            metadata.SaveOriginalValue(updatedTransition.Trigger, originalTransition.InternalTransitionIndex);
            return true;
        }
Beispiel #2
0
        protected override void OnCreateDynamicUpdateMap(NativeActivityUpdateMapMetadata metadata, Activity originalActivity)
        {
            Flowchart originalFlowchart = (Flowchart)originalActivity;
            Dictionary <Activity, int> originalActivities = new Dictionary <Activity, int>();

            foreach (FlowNode node in originalFlowchart.reachableNodes)
            {
                if (node.ChildActivity == null)
                {
                    continue;
                }
                if (metadata.IsReferenceToImportedChild(node.ChildActivity))
                {
                    // We can't save original values for referenced children. Also, we can't
                    // reliably combine implementation changes with changes to referenced children.
                    // For now, we just disable this scenario altogether; if we want to support it,
                    // we'll need deeper runtime support.
                    metadata.DisallowUpdateInsideThisActivity(SR.FlowchartContainsReferences);
                    return;
                }
                if (originalActivities.ContainsKey(node.ChildActivity))
                {
                    metadata.DisallowUpdateInsideThisActivity(SR.MultipleFlowNodesSharingSameChildBlockDU);
                    return;
                }

                originalActivities[node.ChildActivity] = node.Index;
            }

            HashSet <Activity> updatedActivities = new HashSet <Activity>();

            foreach (FlowNode node in this.reachableNodes)
            {
                if (node.ChildActivity != null)
                {
                    if (metadata.IsReferenceToImportedChild(node.ChildActivity))
                    {
                        metadata.DisallowUpdateInsideThisActivity(SR.FlowchartContainsReferences);
                        return;
                    }

                    if (updatedActivities.Contains(node.ChildActivity))
                    {
                        metadata.DisallowUpdateInsideThisActivity(SR.MultipleFlowNodesSharingSameChildBlockDU);
                        return;
                    }
                    else
                    {
                        updatedActivities.Add(node.ChildActivity);
                    }

                    Activity originalChild = metadata.GetMatch(node.ChildActivity);
                    int      originalIndex;
                    if (originalChild != null && originalActivities.TryGetValue(originalChild, out originalIndex))
                    {
                        if (originalFlowchart.reachableNodes[originalIndex].GetType() != node.GetType())
                        {
                            metadata.DisallowUpdateInsideThisActivity(SR.CannotMoveChildAcrossDifferentFlowNodeTypes);
                            return;
                        }

                        if (originalIndex != node.Index)
                        {
                            metadata.SaveOriginalValue(node.ChildActivity, originalIndex);
                        }
                    }
                }
            }
        }
Beispiel #3
0
        private static bool ValidateDUInConditionTransition(NativeActivityUpdateMapMetadata metadata, InternalTransition updatedTransition, InternalTransition originalTransition, out string errorMessage)
        {
            Fx.Assert(!originalTransition.IsUnconditional, "Transition should be conditional in the original definition.");
            errorMessage = string.Empty;

            foreach (TransitionData updatedTData in updatedTransition.TransitionDataList)
            {
                if (metadata.IsReferenceToImportedChild(updatedTData.Condition))
                {
                    // if the trigger is referenced, it might have another save values already.
                    errorMessage = SR.TriggerOrConditionIsReferenced;
                    return false;
                }

                Fx.Assert(null != updatedTData.Condition, "Must be a condition transition.");
                Activity conditionMatch = metadata.GetMatch(updatedTData.Condition);

                if (null == conditionMatch && null != metadata.GetMatch(updatedTData.Action))
                {
                    // new Transition.Condition with an Transition.Action moved from within the InternalState.
                    errorMessage = SR.MovingActivitiesInStateBlockDU;
                    return false;
                }
                else if (null != conditionMatch)
                {
                    bool foundMatchingOriginalCondition = false;

                    for (int transitionIndex = 0; transitionIndex < originalTransition.TransitionDataList.Count; transitionIndex++)
                    {
                        if (object.ReferenceEquals(originalTransition.TransitionDataList[transitionIndex].Condition, conditionMatch))
                        {
                            foundMatchingOriginalCondition = true;

                            // found the original matching condition in updated transition definition.
                            TransitionData originalTData = originalTransition.TransitionDataList[transitionIndex];

                            Activity originalAction = originalTData.Action;

                            // NOTE: Transition.Action is allowed to be removed, because it doesn't change the execution semantics of SM
                            // if this removed activity was executing, WF runtime would disallow the update.
                            Activity actionMatch = metadata.GetMatch(updatedTData.Action);

                            if (null != actionMatch && !object.ReferenceEquals(originalAction, actionMatch))
                            {
                                // Transition.Action is an activity moved from elsewhere within the InternalState
                                errorMessage = SR.MovingActivitiesInStateBlockDU;
                                return false;
                            }

                            metadata.SaveOriginalValue(updatedTransition.Trigger, originalTransition.InternalTransitionIndex);
                            metadata.SaveOriginalValue(updatedTData.Condition, transitionIndex);
                        }
                    }

                    if (!foundMatchingOriginalCondition)
                    {
                        // another child activity is move to the Transition.Condition.
                        errorMessage = SR.DUDisallowIfCannotFindingMatchingCondition;
                        return false;
                    }
                }
            }

            return true;
        }