예제 #1
0
        static void ThrowIfMapsIncompatible(DynamicUpdateMap first, DynamicUpdateMap second, MergeErrorContext errorContext)
        {
            Fx.Assert(!first.IsNoChanges && !second.IsNoChanges, "This method is never supposed to be called on the NoChanges map.");

            if (first.IsForImplementation != second.IsForImplementation)
            {
                errorContext.Throw(SR.InvalidMergeMapForImplementation(first.IsForImplementation, second.IsForImplementation));
            }
            if (first.NewDefinitionMemberCount != second.OldDefinitionMemberCount)
            {
                errorContext.Throw(SR.InvalidMergeMapMemberCount(first.NewDefinitionMemberCount, second.OldDefinitionMemberCount));
            }
            if (!first.ArgumentsAreUnknown && !second.ArgumentsAreUnknown && first.IsForImplementation &&
                !ActivityComparer.ListEquals(first.newArguments, second.oldArguments))
            {
                if (first.NewArguments.Count != second.OldArguments.Count)
                {
                    errorContext.Throw(SR.InvalidMergeMapArgumentCount(first.NewArguments.Count, second.OldArguments.Count));
                }
                else
                {
                    errorContext.Throw(SR.InvalidMergeMapArgumentsChanged);
                }
            }
        }
예제 #2
0
            bool CompareVariableEqualityAndAddActivitiesPair(Variable currentVariable, Variable originalVariable)
            {
                if (!ActivityComparer.CompareVariableEquality(currentVariable, originalVariable))
                {
                    return(false);
                }

                if (currentVariable.Default != null)
                {
                    Fx.Assert(originalVariable.Default != null, "both Defaults are either non-null or null.");
                    this.PrepareToMatchSubtree(currentVariable.Default, originalVariable.Default);
                }

                return(true);
            }
예제 #3
0
            bool CompareDelegateEqualityAndAddActivitiesPair(ActivityDelegate currentDelegate, ActivityDelegate originalDelegate)
            {
                if (!ActivityComparer.CompareDelegateEquality(currentDelegate, originalDelegate))
                {
                    return(false);
                }

                if (currentDelegate.Handler != null)
                {
                    Fx.Assert(originalDelegate.Handler != null, "both handlers are either non-null or null.");
                    this.PrepareToMatchSubtree(currentDelegate.Handler, originalDelegate.Handler);
                }

                return(true);
            }
예제 #4
0
            bool TryPreparingArgumentExpressions(RuntimeArgument originalArg, RuntimeArgument updatedArg)
            {
                if (!ActivityComparer.CompareArgumentEquality(updatedArg, originalArg))
                {
                    return(false);
                }

                if (updatedArg.BoundArgument != null && updatedArg.BoundArgument.Expression != null)
                {
                    Fx.Assert(originalArg.BoundArgument != null && originalArg.BoundArgument.Expression != null, "both Expressions are either non-null or null.");
                    this.PrepareToMatchSubtree(updatedArg.BoundArgument.Expression, originalArg.BoundArgument.Expression);
                }

                return(true);
            }
예제 #5
0
        // Wrap an implementation map in a dummy map. This allows use of an implementation map as the
        // root map in the case when the root is an x:Class with no public children.
        internal DynamicUpdateMap AsRootMap()
        {
            Fx.Assert(this.IsForImplementation, "This should only be called on implementation map");

            if (!ActivityComparer.ListEquals(this.NewArguments, this.OldArguments))
            {
                throw FxTrace.Exception.AsError(new InstanceUpdateException(SR.InvalidImplementationAsWorkflowRootForRuntimeStateBecauseArgumentsChanged));
            }

            DynamicUpdateMap result = new DynamicUpdateMap
            {
                IsImplementationAsRoot   = true,
                NewDefinitionMemberCount = 1
            };

            result.AddEntry(new DynamicUpdateMapEntry(1, 1)
            {
                ImplementationUpdateMap = this,
            });
            return(result);
        }
예제 #6
0
            public bool Match(out DynamicUpdateMap argumentChangesMap)
            {
                argumentChangesMap = null;

                int  nextOriginalSubrootId   = 0;
                int  nextUpdatedSubrootId    = 0;
                bool allSubtreeRootsEnqueued = false;

                // enqueue all subtree root pairs first
                while (!allSubtreeRootsEnqueued)
                {
                    nextOriginalSubrootId = GetIndexOfNextSubtreeRoot(this.originalPrivateIdSpace, nextOriginalSubrootId);
                    nextUpdatedSubrootId  = GetIndexOfNextSubtreeRoot(this.updatedPrivateIdSpace, nextUpdatedSubrootId);

                    if (nextOriginalSubrootId != -1 && nextUpdatedSubrootId != -1)
                    {
                        // found next disjoint subtree pair to match
                        this.PrepareToMatchSubtree(this.updatedPrivateIdSpace[nextUpdatedSubrootId], this.originalPrivateIdSpace[nextOriginalSubrootId]);
                    }
                    else if (nextOriginalSubrootId == -1 && nextUpdatedSubrootId == -1)
                    {
                        // there are no more subtree root pair to process.
                        allSubtreeRootsEnqueued = true;
                    }
                    else
                    {
                        // something other than Arguments must have changed
                        return(false);
                    }
                }

                while (this.matchedActivities.Count > 0)
                {
                    Tuple <Activity, Activity> pair = this.matchedActivities.Dequeue();
                    Activity originalActivity       = pair.Item1;
                    Activity currentActivity        = pair.Item2;

                    Fx.Assert(originalActivity.MemberOf == this.originalPrivateIdSpace && currentActivity.MemberOf == this.updatedPrivateIdSpace, "neither activities must be a reference.");

                    if (currentActivity.GetType() != originalActivity.GetType() || currentActivity.RelationshipToParent != originalActivity.RelationshipToParent)
                    {
                        return(false);
                    }

                    // there is no need to perform CompareChildEquality since we already compare ActivityId and activity.GetType() as above for all activities in the IdSpace, and check on the collection count
                    if (!ActivityComparer.ListEquals(
                            ActivityComparer.GetDeclaredChildren(currentActivity.Children, currentActivity),
                            ActivityComparer.GetDeclaredChildren(originalActivity.Children, originalActivity),
                            this.AddEqualChildren))
                    {
                        return(false);
                    }

                    // there is no need to perform CompareChildEquality since we already compare ActivityId and activity.GetType() as above for all activities in the IdSpace, and check on the collection count
                    if (!ActivityComparer.ListEquals(
                            ActivityComparer.GetDeclaredChildren(currentActivity.ImportedChildren, currentActivity),
                            ActivityComparer.GetDeclaredChildren(originalActivity.ImportedChildren, originalActivity),
                            this.AddEqualChildren))
                    {
                        return(false);
                    }

                    if (!ActivityComparer.ListEquals <ActivityDelegate>(
                            ActivityComparer.GetDeclaredDelegates(currentActivity.Delegates, currentActivity),
                            ActivityComparer.GetDeclaredDelegates(originalActivity.Delegates, originalActivity),
                            this.CompareDelegateEqualityAndAddActivitiesPair))
                    {
                        return(false);
                    }

                    if (!ActivityComparer.ListEquals <ActivityDelegate>(
                            ActivityComparer.GetDeclaredDelegates(currentActivity.ImportedDelegates, currentActivity),
                            ActivityComparer.GetDeclaredDelegates(originalActivity.ImportedDelegates, originalActivity),
                            this.CompareDelegateEqualityAndAddActivitiesPair))
                    {
                        return(false);
                    }

                    if (!ActivityComparer.ListEquals <Variable>(currentActivity.RuntimeVariables, originalActivity.RuntimeVariables, this.CompareVariableEqualityAndAddActivitiesPair))
                    {
                        return(false);
                    }

                    // with all runtime metadata except arguments matching,
                    // the current activities pair qualifies as a matching entry
                    // let's create an entry
                    DynamicUpdateMapEntry entry = new DynamicUpdateMapEntry(originalActivity.InternalId, currentActivity.InternalId);
                    this.privateMap.AddEntry(entry);

                    if (!this.TryMatchingArguments(entry, originalActivity, currentActivity))
                    {
                        return(false);
                    }
                }

                // there are no more activities-pair to process.
                // if we are here, it means we have successfully matched the private IdSpace pair
                if (this.argumentChangeDetected)
                {
                    // return the generated map only if we have argument entries
                    argumentChangesMap = this.privateMap;
                }

                return(true);
            }