1 //----------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //----------------------------------------------------------------
4 
5 namespace System.Activities.Debugger
6 {
7     using System.Collections.Generic;
8     using System.Activities.Debugger.Symbol;
9 
10     // Keep track of instrumentation information.
11     // - which subroot has source file but not yet instrumented.
12     // - which subroots share the same source file
13     // SubRoot is defined as an activity that has a source file
14     // (Custom Activity).
15     class InstrumentationTracker
16     {
17         // Root of the workflow to keep track.
18         Activity root;
19 
20         // Mapping of subroots to their source files.
21         Dictionary<Activity, string> uninstrumentedSubRoots;
22 
23         Dictionary<Activity, string> UninstrumentedSubRoots
24         {
25             get
26             {
27                 if (this.uninstrumentedSubRoots == null)
28                 {
29                     InitializeUninstrumentedSubRoots();
30                 }
31                 return this.uninstrumentedSubRoots;
32             }
33         }
34 
InstrumentationTracker(Activity root)35         public InstrumentationTracker(Activity root)
36         {
37             this.root = root;
38         }
39 
40         // Initialize UninstrumentedSubRoots by traversing the workflow.
InitializeUninstrumentedSubRoots()41         void InitializeUninstrumentedSubRoots()
42         {
43             this.uninstrumentedSubRoots = new Dictionary<Activity, string>();
44 
45             Queue<Activity> activitiesRemaining = new Queue<Activity>();
46 
47             CollectSubRoot(this.root);
48             activitiesRemaining.Enqueue(this.root);
49 
50             while (activitiesRemaining.Count > 0)
51             {
52                 Activity toProcess = activitiesRemaining.Dequeue();
53 
54                 foreach (Activity activity in WorkflowInspectionServices.GetActivities(toProcess))
55                 {
56                     if (!uninstrumentedSubRoots.ContainsKey(activity))
57                     {
58                         CollectSubRoot(activity);
59                         activitiesRemaining.Enqueue(activity);
60                     }
61                 }
62             }
63         }
64 
65         // Collect subroot as uninstrumented activity.
CollectSubRoot(Activity activity)66         void CollectSubRoot(Activity activity)
67         {
68             string wfSymbol = DebugSymbol.GetSymbol(activity) as string;
69             if (!string.IsNullOrEmpty(wfSymbol))
70             {
71                 this.uninstrumentedSubRoots.Add(activity, wfSymbol);
72             }
73             else
74             {
75                 string sourcePath = XamlDebuggerXmlReader.GetFileName(activity) as string;
76                 if (!string.IsNullOrEmpty(sourcePath))
77                 {
78                     this.uninstrumentedSubRoots.Add(activity, sourcePath);
79                 }
80             }
81         }
82 
83         // Whether this is unistrumented sub root.
IsUninstrumentedSubRoot(Activity subRoot)84         public bool IsUninstrumentedSubRoot(Activity subRoot)
85         {
86             return this.UninstrumentedSubRoots.ContainsKey(subRoot);
87         }
88 
89 
90         // Returns Activities that have the same source as the given subRoot.
91         // This will return other instantiation of the same custom activity.
92         // Needed to avoid re-instrumentation of the same file.
GetSameSourceSubRoots(Activity subRoot)93         public List<Activity> GetSameSourceSubRoots(Activity subRoot)
94         {
95             string sourcePath;
96             List<Activity> sameSourceSubRoots = new List<Activity>();
97             if (this.UninstrumentedSubRoots.TryGetValue(subRoot, out sourcePath))
98             {
99                 foreach (KeyValuePair<Activity, string> entry in this.UninstrumentedSubRoots)
100                 {
101                     if (entry.Value == sourcePath && entry.Key != subRoot)
102                     {
103                         sameSourceSubRoots.Add(entry.Key);
104                     }
105                 }
106             }
107             return sameSourceSubRoots;
108         }
109 
110         // Mark this sub root as instrumented.
MarkInstrumented(Activity subRoot)111         public void MarkInstrumented(Activity subRoot)
112         {
113             this.UninstrumentedSubRoots.Remove(subRoot);
114         }
115     }
116 }
117