protected virtual void OnCreateDynamicUpdateMap(NativeActivityUpdateMapMetadata metadata, Activity originalActivity)
 {
     // default UpdateMapMetadata.AllowUpdateInsideThisActivity is TRUE
     if (!metadata.IsUpdateExplicitlyAllowedOrDisallowed && !DoPublicChildrenMatch(metadata, this, originalActivity))
     {
         metadata.DisallowUpdateInsideThisActivity(SR.PublicChildrenChangeBlockDU);
     }
 }
Beispiel #2
0
            protected override void OnCreateDynamicUpdateMap(NativeActivityUpdateMapMetadata metadata, Activity originalActivity)
            {
                PickBranchBody originalBranchBody = (PickBranchBody)originalActivity;

                if ((originalBranchBody.Action != null && metadata.GetMatch(this.Trigger) == originalBranchBody.Action) || (this.Action != null && metadata.GetMatch(this.Action) == originalBranchBody.Trigger))
                {
                    metadata.DisallowUpdateInsideThisActivity(SR.PickBranchTriggerActionSwapped);
                    return;
                }

                metadata.AllowUpdateInsideThisActivity();
            }
Beispiel #3
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 #4
0
        protected override void OnCreateDynamicUpdateMap(NativeActivityUpdateMapMetadata metadata, Activity originalActivity)
        {
            InternalState originalInternalState = (InternalState)originalActivity;

            // NOTE: State.Entry/Exit are 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 entryActivityMatch = metadata.GetMatch(this.Entry);
            Activity exitActivityMatch = metadata.GetMatch(this.Exit);

            if ((null != entryActivityMatch && !object.ReferenceEquals(entryActivityMatch, originalInternalState.Entry)) ||
                (null != exitActivityMatch && !object.ReferenceEquals(exitActivityMatch, originalInternalState.Exit)))
            {
                // original State.Entry/Exit is replaced with another child activities with InternalState
                // new State.Entry/Exit is moved from another child activities within InternalState.
                metadata.DisallowUpdateInsideThisActivity(SR.MovingActivitiesInStateBlockDU);
                return;
            }

            int originalTriggerInUpdatedDefinition = 0;
            
            foreach (InternalTransition originalTransition in originalInternalState.internalTransitions)
            {
                if (metadata.IsReferenceToImportedChild(originalTransition.Trigger))
                {
                    metadata.DisallowUpdateInsideThisActivity(SR.TriggerOrConditionIsReferenced);
                    return;
                }
                
                if (!originalTransition.IsUnconditional)
                {
                    // new Trigger activity
                    foreach (TransitionData transitionData in originalTransition.TransitionDataList)
                    {
                        if (metadata.IsReferenceToImportedChild(transitionData.Condition))
                        {
                            metadata.DisallowUpdateInsideThisActivity(SR.TriggerOrConditionIsReferenced);
                            return;
                        }
                    }
                }
            }

            foreach (InternalTransition updatedTransition in this.internalTransitions)
            {
                if (metadata.IsReferenceToImportedChild(updatedTransition.Trigger))
                {
                    // if the trigger is referenced, it might have another save values already.
                    metadata.DisallowUpdateInsideThisActivity(SR.TriggerOrConditionIsReferenced);
                    return;
                }

                Activity triggerMatch = metadata.GetMatch(updatedTransition.Trigger);

                if (null != triggerMatch)
                {
                    InternalTransition originalTransition;

                    if (originalInternalState.triggerInternalTransitionMapping.TryGetValue(triggerMatch, out originalTransition))
                    {
                        originalTriggerInUpdatedDefinition++;

                        if (originalTransition.IsUnconditional)
                        {
                            string errorMessage;
                            bool canTransitionBeUpdated = ValidateDUInUnconditionalTransition(metadata, updatedTransition, originalTransition, out errorMessage);

                            if (!canTransitionBeUpdated)
                            {
                                metadata.DisallowUpdateInsideThisActivity(errorMessage);
                                return;
                            }
                        }
                        else
                        {
                            if (updatedTransition.IsUnconditional)
                            {
                                // cannot change the transition from condition to unconditional.
                                metadata.DisallowUpdateInsideThisActivity(SR.ChangeConditionalTransitionToUnconditionalBlockDU);
                                return;
                            }
                            else
                            {
                                string errorMessage;
                                bool canTransitionBeUpdated = ValidateDUInConditionTransition(metadata, updatedTransition, originalTransition, out errorMessage);

                                if (!canTransitionBeUpdated)
                                {
                                    metadata.DisallowUpdateInsideThisActivity(errorMessage);
                                    return;
                                }
                            }
                        }
                    }
                    else
                    {
                        // the trigger is an child activity moved from elsewhere within the state
                        metadata.DisallowUpdateInsideThisActivity(SR.MovingActivitiesInStateBlockDU);
                        return;
                    }
                }
                else
                {
                    // new Trigger activity
                    foreach (TransitionData transitionData in updatedTransition.TransitionDataList)
                    {
                        if ((null != transitionData.Condition && null != metadata.GetMatch(transitionData.Condition)) ||
                            (null != transitionData.Action && null != metadata.GetMatch(transitionData.Action)))
                        {
                            // if a new transition is added, it is expected that the Condition/Action 
                            // are newly created.
                            metadata.DisallowUpdateInsideThisActivity(SR.ChangingTriggerOrUseOriginalConditionActionBlockDU);
                            return;
                        }
                    }
                }
            }
            
            if (originalTriggerInUpdatedDefinition != originalInternalState.internalTransitions.Count)
            {
                // NOTE: in general, if the transition is removed when there are pending triggers,
                // runtime would be able to detect the missing child activities.  However, in cases,
                // where the transition is happening already (in between completion of Transition.Action
                // callback but before InternalState is completed), the workflow definition can be unloaded
                // and updated.  The InternalState is unable to trace the original transition that set the 
                // destination state index.  In that case, the update would fail at UpdateInstance.
                // To simplify the model, it is more convenient to disallow removing existing transitions
                // from an executing InternalState.  The only extra restriction it brings, is that it disables
                // update even if the InternalState is uploaded at State.Entry.  This scenario, however, is uncommon.
                metadata.DisallowUpdateInsideThisActivity(SR.RemovingTransitionsBlockDU);
            }
        }