1 // Copyright (c) Microsoft Corporation. All rights reserved.
3 // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
4 // WHETHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
5 // WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
6 // THE ENTIRE RISK OF USE OR RESULTS IN CONNECTION WITH THE USE OF THIS CODE
7 // AND INFORMATION REMAINS WITH THE USER.
10 /*********************************************************************
11 * NOTE: A copy of this file exists at: WF\Activities\Common
12 * The two files must be kept in sync. Any change made here must also
13 * be made to WF\Activities\Common\ValidationHelpers.cs
14 *********************************************************************/
15 namespace System.Workflow.ComponentModel.Compiler
20 using System.Diagnostics;
21 using System.Collections;
22 using System.Collections.Generic;
23 using System.Reflection;
24 using System.CodeDom.Compiler;
25 using System.Workflow.ComponentModel.Design;
26 using System.Workflow.ComponentModel.Compiler;
27 using System.Collections.Specialized;
28 using System.ComponentModel.Design.Serialization;
31 internal static class ValidationHelpers
33 #region Validation & helpers for ID and Type
35 internal static void ValidateIdentifier(IServiceProvider serviceProvider, string identifier)
37 if (serviceProvider == null)
38 throw new ArgumentNullException("serviceProvider");
40 SupportedLanguages language = CompilerHelpers.GetSupportedLanguage(serviceProvider);
41 CodeDomProvider provider = CompilerHelpers.GetCodeDomProvider(language);
42 if (language == SupportedLanguages.CSharp && identifier.StartsWith("@", StringComparison.Ordinal) ||
43 language == SupportedLanguages.VB && identifier.StartsWith("[", StringComparison.Ordinal) && identifier.EndsWith("]", StringComparison.Ordinal) ||
44 !provider.IsValidIdentifier(identifier))
46 throw new Exception(SR.GetString(SR.Error_InvalidLanguageIdentifier, identifier));
50 internal static ValidationError ValidateIdentifier(string propName, IServiceProvider context, string identifier)
53 throw new ArgumentNullException("context");
55 ValidationError error = null;
56 if (identifier == null || identifier.Length == 0)
57 error = new ValidationError(SR.GetString(SR.Error_PropertyNotSet, propName), ErrorNumbers.Error_PropertyNotSet);
62 ValidationHelpers.ValidateIdentifier(context, identifier);
66 error = new ValidationError(SR.GetString(SR.Error_InvalidIdentifier, propName, e.Message), ErrorNumbers.Error_InvalidIdentifier);
70 error.PropertyName = propName;
74 internal static ValidationError ValidateNameProperty(string propName, IServiceProvider context, string identifier)
77 throw new ArgumentNullException("context");
79 ValidationError error = null;
80 if (identifier == null || identifier.Length == 0)
81 error = new ValidationError(SR.GetString(SR.Error_PropertyNotSet, propName), ErrorNumbers.Error_PropertyNotSet);
84 SupportedLanguages language = CompilerHelpers.GetSupportedLanguage(context);
85 CodeDomProvider provider = CompilerHelpers.GetCodeDomProvider(language);
87 if (language == SupportedLanguages.CSharp && identifier.StartsWith("@", StringComparison.Ordinal) ||
88 language == SupportedLanguages.VB && identifier.StartsWith("[", StringComparison.Ordinal) && identifier.EndsWith("]", StringComparison.Ordinal) ||
89 !provider.IsValidIdentifier(provider.CreateEscapedIdentifier(identifier)))
91 error = new ValidationError(SR.GetString(SR.Error_InvalidIdentifier, propName, SR.GetString(SR.Error_InvalidLanguageIdentifier, identifier)), ErrorNumbers.Error_InvalidIdentifier);
95 error.PropertyName = propName;
99 internal static ValidationErrorCollection ValidateUniqueIdentifiers(Activity rootActivity)
101 if (rootActivity == null)
102 throw new ArgumentNullException("rootActivity");
104 Hashtable identifiers = new Hashtable();
105 ValidationErrorCollection validationErrors = new ValidationErrorCollection();
106 Queue activities = new Queue();
107 activities.Enqueue(rootActivity);
108 while (activities.Count > 0)
110 Activity activity = (Activity)activities.Dequeue();
111 if (activity.Enabled)
113 if (identifiers.ContainsKey(activity.QualifiedName))
115 ValidationError duplicateError = new ValidationError(SR.GetString(SR.Error_DuplicatedActivityID, activity.QualifiedName), ErrorNumbers.Error_DuplicatedActivityID);
116 duplicateError.PropertyName = "Name";
117 duplicateError.UserData[typeof(Activity)] = activity;
118 validationErrors.Add(duplicateError);
121 identifiers.Add(activity.QualifiedName, activity);
123 if (activity is CompositeActivity && ((activity.Parent == null) || !Helpers.IsCustomActivity(activity as CompositeActivity)))
125 foreach (Activity child in Helpers.GetAllEnabledActivities((CompositeActivity)activity))
126 activities.Enqueue(child);
131 return validationErrors;
136 #region Validation for Activity Ref order
138 internal static bool IsActivitySourceInOrder(Activity request, Activity response)
140 if (request.Parent == null)
142 List<Activity> responsePath = new List<Activity>();
143 responsePath.Add(response);
144 Activity responseParent = response is CompositeActivity ? (CompositeActivity)response : response.Parent;
145 while (responseParent != null)
147 responsePath.Add(responseParent);
148 responseParent = responseParent.Parent;
151 Activity requestChild = request;
152 CompositeActivity requestParent = request is CompositeActivity ? (CompositeActivity)request : request.Parent;
153 while (requestParent != null && !responsePath.Contains(requestParent))
155 requestChild = requestParent;
156 requestParent = requestParent.Parent;
159 if (requestParent == requestChild)
162 bool incorrectOrder = false;
163 int index = (responsePath.IndexOf(requestParent) - 1);
164 index = (index < 0) ? 0 : index; //sometimes parent gets added to the collection twice which causes index to be -1
165 Activity responseChild = responsePath[index];
167 if (requestParent == null || Helpers.IsAlternateFlowActivity(requestChild) || Helpers.IsAlternateFlowActivity(responseChild))
168 incorrectOrder = true;
171 for (int i = 0; i < requestParent.EnabledActivities.Count; i++)
173 if (requestParent.EnabledActivities[i] == requestChild)
175 else if (requestParent.EnabledActivities[i] == responseChild)
177 incorrectOrder = true;
182 return !incorrectOrder;
187 internal static ValidationErrorCollection ValidateObject(ValidationManager manager, object obj)
189 ValidationErrorCollection errors = new ValidationErrorCollection();
193 Type objType = obj.GetType();
194 if (!objType.IsPrimitive && (objType != typeof(string)))
196 bool removeValidatedObjectCollection = false;
197 Dictionary<int, object> validatedObjects = manager.Context[typeof(Dictionary<int, object>)] as Dictionary<int, object>;
198 if (validatedObjects == null)
200 validatedObjects = new Dictionary<int, object>();
201 manager.Context.Push(validatedObjects);
202 removeValidatedObjectCollection = true;
207 if (!validatedObjects.ContainsKey(obj.GetHashCode()))
209 validatedObjects.Add(obj.GetHashCode(), obj);
212 Validator[] validators = manager.GetValidators(objType);
213 foreach (Validator validator in validators)
214 errors.AddRange(validator.Validate(manager, obj));
218 validatedObjects.Remove(obj.GetHashCode());
224 if (removeValidatedObjectCollection)
225 manager.Context.Pop();
232 internal static ValidationErrorCollection ValidateActivity(ValidationManager manager, Activity activity)
234 ValidationErrorCollection errors = ValidationHelpers.ValidateObject(manager, activity);
236 foreach (ValidationError error in errors)
238 if (!error.UserData.Contains(typeof(Activity)))
239 error.UserData[typeof(Activity)] = activity;
244 internal static ValidationErrorCollection ValidateProperty(ValidationManager manager, Activity activity, object obj, PropertyValidationContext propertyValidationContext)
246 return ValidateProperty(manager, activity, obj, propertyValidationContext, null);
249 internal static ValidationErrorCollection ValidateProperty(ValidationManager manager, Activity activity, object obj, PropertyValidationContext propertyValidationContext, object extendedPropertyContext)
252 throw new ArgumentNullException("manager");
254 throw new ArgumentNullException("obj");
255 if (propertyValidationContext == null)
256 throw new ArgumentNullException("propertyValidationContext");
258 ValidationErrorCollection errors = new ValidationErrorCollection();
260 manager.Context.Push(activity);
261 manager.Context.Push(propertyValidationContext);
262 if (extendedPropertyContext != null)
263 manager.Context.Push(extendedPropertyContext);
266 errors.AddRange(ValidationHelpers.ValidateObject(manager, obj));
270 manager.Context.Pop();
271 manager.Context.Pop();
272 if (extendedPropertyContext != null)
273 manager.Context.Pop();