1 // ---------------------------------------------------------------------------
2 // Copyright (C) 2006 Microsoft Corporation All Rights Reserved
3 // ---------------------------------------------------------------------------
4 
5 #define CODE_ANALYSIS
6 using System.Collections.Generic;
7 using System.ComponentModel;
8 using System.Diagnostics.CodeAnalysis;
9 using System.Workflow.ComponentModel;
10 
11 namespace System.Workflow.Activities.Rules
12 {
13     #region class RuleDefinitions
14 
15     public sealed class RuleDefinitions : IWorkflowChangeDiff
16     {
17 
18         [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes")]
19         public static readonly DependencyProperty RuleDefinitionsProperty = DependencyProperty.RegisterAttached("RuleDefinitions", typeof(RuleDefinitions), typeof(RuleDefinitions), new PropertyMetadata(null, DependencyPropertyOptions.Metadata, new GetValueOverride(OnGetRuleConditions), null, new Attribute[] { new DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Hidden) }));
20 
21         private RuleConditionCollection conditions;
22         private RuleSetCollection ruleSets;
23         private bool runtimeInitialized;
24         [NonSerialized]
25         private object syncLock = new object();
26 
27         [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
28         public RuleConditionCollection Conditions
29         {
30             get
31             {
32                 if (this.conditions == null)
33                     this.conditions = new RuleConditionCollection();
34                 return conditions;
35             }
36         }
37 
38         [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
39         public RuleSetCollection RuleSets
40         {
41             get
42             {
43                 if (this.ruleSets == null)
44                     this.ruleSets = new RuleSetCollection();
45                 return this.ruleSets;
46             }
47         }
48 
OnGetRuleConditions(DependencyObject dependencyObject)49         internal static object OnGetRuleConditions(DependencyObject dependencyObject)
50         {
51             if (dependencyObject == null)
52                 throw new ArgumentNullException("dependencyObject");
53 
54             RuleDefinitions rules = dependencyObject.GetValueBase(RuleDefinitions.RuleDefinitionsProperty) as RuleDefinitions;
55             if (rules != null)
56                 return rules;
57 
58             Activity rootActivity = dependencyObject as Activity;
59             if (rootActivity.Parent == null)
60             {
61                 rules = ConditionHelper.GetRuleDefinitionsFromManifest(rootActivity.GetType());
62                 if (rules != null)
63                     dependencyObject.SetValue(RuleDefinitions.RuleDefinitionsProperty, rules);
64             }
65             return rules;
66         }
67 
OnRuntimeInitialized()68         internal void OnRuntimeInitialized()
69         {
70             lock (syncLock)
71             {
72                 if (runtimeInitialized)
73                     return;
74                 Conditions.OnRuntimeInitialized();
75                 RuleSets.OnRuntimeInitialized();
76                 runtimeInitialized = true;
77             }
78         }
79 
80         #region IWorkflowChangeDiff Members
81 
Diff(object originalDefinition, object changedDefinition)82         public IList<WorkflowChangeAction> Diff(object originalDefinition, object changedDefinition)
83         {
84             RuleDefinitions originalRules = originalDefinition as RuleDefinitions;
85             RuleDefinitions changedRules = changedDefinition as RuleDefinitions;
86             if ((originalRules == null) || (changedRules == null))
87                 return new List<WorkflowChangeAction>();
88 
89             IList<WorkflowChangeAction> cdiff = Conditions.Diff(originalRules.Conditions, changedRules.Conditions);
90             IList<WorkflowChangeAction> rdiff = RuleSets.Diff(originalRules.RuleSets, changedRules.RuleSets);
91 
92             // quick optimization -- if no condition changes, simply return the ruleset changes
93             if (cdiff.Count == 0)
94                 return rdiff;
95 
96             // merge ruleset changes into condition changes
97             for (int i = 0; i < rdiff.Count; ++i)
98             {
99                 cdiff.Add(rdiff[i]);
100             }
101             return cdiff;
102         }
103         #endregion
104 
Clone()105         internal RuleDefinitions Clone()
106         {
107             RuleDefinitions newRuleDefinitions = new RuleDefinitions();
108 
109             if (this.ruleSets != null)
110             {
111                 newRuleDefinitions.ruleSets = new RuleSetCollection();
112                 foreach (RuleSet r in this.ruleSets)
113                     newRuleDefinitions.ruleSets.Add(r.Clone());
114             }
115 
116             if (this.conditions != null)
117             {
118                 newRuleDefinitions.conditions = new RuleConditionCollection();
119                 foreach (RuleCondition r in this.conditions)
120                     newRuleDefinitions.conditions.Add(r.Clone());
121             }
122 
123             return newRuleDefinitions;
124         }
125     }
126     #endregion
127 }
128