Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Activities.Core.Presentation / System / Activities / Core / Presentation / StateMachineValidationErrorSourceLocator.cs
1 // <copyright>
2 //   Copyright (c) Microsoft Corporation.  All rights reserved.
3 // </copyright>
4
5 namespace System.Activities.Core.Presentation
6 {
7     using System.Activities.Presentation.Validation;
8     using System.Activities.Statements;
9     using System.Collections.Generic;
10     using System.Runtime;
11
12     internal class StateMachineValidationErrorSourceLocator : IValidationErrorSourceLocator
13     {
14         public List<object> FindSourceDetailFromActivity(Activity errorSource, object errorSourceDetail)
15         {
16             if (errorSourceDetail == null)
17             {
18                 return new List<object> { errorSource };
19             }
20             else
21             {
22                 return FindRelativePath((StateMachine)errorSource, errorSourceDetail);
23             }
24         }
25
26         // case 1: StateMachine -> Default expression of StateMachine's variable -> ...
27         // case 2: StateMachine -> InternalState -> ...
28         public void ReplaceParentChainWithSource(Activity parentActivity, List<object> parentChain)
29         {
30             Activity lastActivity = parentChain[parentChain.Count - 1] as Activity;
31             StateMachine stateMachine = (StateMachine)parentActivity;
32
33             foreach (Variable variable in stateMachine.Variables)
34             {
35                 if (variable != null && variable.Default == lastActivity)
36                 {
37                     parentChain.Add(stateMachine);
38                     return;
39                 }
40             }
41
42             if (parentChain.Count > 1)
43             {
44                 // assume lastActivity is InternalState
45
46                 // remove InternalState
47                 parentChain.RemoveAt(parentChain.Count - 1);
48
49                 Activity targetActivity = (Activity)parentChain[parentChain.Count - 1];
50
51                 // the targetActivity will be available in the path
52                 parentChain.RemoveAt(parentChain.Count - 1);
53
54                 List<object> path = FindRelativePath(stateMachine, targetActivity);
55
56                 foreach (object pathObject in path)
57                 {
58                     parentChain.Add(pathObject);
59                 }
60             }
61         }
62
63         private static List<object> FindRelativePath(StateMachine machine, object descendent)
64         {
65             List<object> path = FindDescendentFromStateMachine(machine, descendent);
66             path.Reverse();
67             return path;
68         }
69
70         private static List<object> FindDescendentFromStateMachine(StateMachine machine, object descendent)
71         {
72             List<object> path = new List<object>();
73             path.Add(machine);
74             foreach (State state in machine.States)
75             {
76                 if (state == descendent)
77                 {
78                     break;
79                 }
80                 else if (state.Entry == descendent)
81                 {
82                     path.Add(state);
83                     break;
84                 }
85                 else if (state.Exit == descendent)
86                 {
87                     path.Add(state);
88                     break;
89                 }
90                 else
91                 {
92                     Transition foundTransition = null;
93                     bool transitionAlone = false;
94                     foreach (Transition transition in state.Transitions)
95                     {
96                         foundTransition = transition;
97                         if (transition == descendent)
98                         {
99                             transitionAlone = true;
100                             break;
101                         }
102                         else if (transition.Trigger == descendent)
103                         {
104                             break;
105                         }
106                         else if (transition.Action == descendent)
107                         {
108                             break;
109                         }
110                         else if (transition.Condition == descendent)
111                         {
112                             break;
113                         }
114                         else
115                         {
116                             foundTransition = null;
117                         }
118                     }
119
120                     if (foundTransition != null)
121                     {
122                         path.Add(state);
123                         if (!transitionAlone)
124                         {
125                             path.Add(foundTransition);
126                         }
127
128                         break;
129                     }
130
131                     bool isVariableError = false;
132                     foreach (Variable variable in state.Variables)
133                     {
134                         if (variable.Default == descendent)
135                         {
136                             isVariableError = true;
137                         }
138                     }
139
140                     if (isVariableError)
141                     {
142                         path.Add(state);
143                         break;
144                     }
145                 }
146             }
147
148             path.Add(descendent);
149             return path;
150         }       
151     }
152 }