Changed to use Authenticate asp.net event instead of Authorize
[castle.git] / Components / Validator / Castle.Components.Validator / ValidatorRunner.cs
blobb47db1f614645f3a540605af04bdb444053a7331
1 // Copyright 2004-2007 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.Components.Validator
17 using System;
18 using System.Collections;
19 using System.Collections.Generic;
20 using System.Reflection;
22 /// <summary>
23 /// Coordinates the gathering and execution of validators.
24 /// <seealso cref="IValidatorRegistry"/>
25 /// </summary>
26 /// <remarks>
27 /// This class is not thread safe and should not be shared. It should only be
28 /// used in small scopes and discarded.
29 /// </remarks>
30 /// <example>
31 /// ValidatorRunner runner = new ValidatorRunner(new CachedValidationRegistry());
32 ///
33 /// if (!runner.IsValid(customer))
34 /// {
35 /// // do something as the Customer instance is not valid
36 /// }
37 /// </example>
38 public class ValidatorRunner
40 private readonly static IDictionary<Type, Type> type2Validator;
41 private readonly IDictionary extendedProperties = new Hashtable();
42 private readonly IDictionary<object, ErrorSummary> errorPerInstance;
43 private readonly bool inferValidators;
44 private readonly IValidatorRegistry registry;
46 static ValidatorRunner()
48 type2Validator = new Dictionary<Type, Type>();
49 type2Validator[typeof(Int16)] = typeof(IntegerValidator);
50 type2Validator[typeof(Nullable<Int16>)] = typeof(NullableIntegerValidator);
51 type2Validator[typeof(Int32)] = typeof(IntegerValidator);
52 type2Validator[typeof(Nullable<Int32>)] = typeof(NullableIntegerValidator);
53 type2Validator[typeof(Int64)] = typeof(IntegerValidator);
54 type2Validator[typeof(Nullable<Int64>)] = typeof(NullableIntegerValidator);
55 type2Validator[typeof(Decimal)] = typeof(DecimalValidator);
56 type2Validator[typeof(Nullable<Decimal>)] = typeof(NullableDecimalValidator);
57 type2Validator[typeof(Single)] = typeof(SingleValidator);
58 type2Validator[typeof(Nullable<Single>)] = typeof(NullableSingleValidator);
59 type2Validator[typeof(Double)] = typeof(DoubleValidator);
60 type2Validator[typeof(Nullable<Double>)] = typeof(NullableDoubleValidator);
61 type2Validator[typeof(DateTime)] = typeof(DateTimeValidator);
62 type2Validator[typeof(Nullable<DateTime>)] = typeof(NullableDateTimeValidator);
65 /// <summary>
66 /// Initializes a new instance of the <see cref="ValidatorRunner"/> class.
67 /// </summary>
68 /// <param name="registry">The registry.</param>
69 public ValidatorRunner(IValidatorRegistry registry) : this(false, registry)
73 /// <summary>
74 /// Initializes a new instance of the <see cref="ValidatorRunner"/> class.
75 /// </summary>
76 /// <param name="inferValidators">If true, the runner will try to infer the validators based on data types</param>
77 /// <param name="registry">The registry.</param>
78 public ValidatorRunner(bool inferValidators, IValidatorRegistry registry)
80 if (registry == null) throw new ArgumentNullException("registry");
82 this.inferValidators = inferValidators;
84 errorPerInstance = new Dictionary<object, ErrorSummary>();
86 this.registry = registry;
89 /// <summary>
90 /// Determines whether the specified instance is valid.
91 /// <para>
92 /// All validators are run.
93 /// </para>
94 /// </summary>
95 /// <param name="objectInstance">The object instance to be validated (cannot be null).</param>
96 /// <returns>
97 /// <see langword="true"/> if the specified obj is valid; otherwise, <see langword="false"/>.
98 /// </returns>
99 public bool IsValid(object objectInstance)
101 return IsValid(objectInstance, RunWhen.Everytime);
104 /// <summary>
105 /// Determines whether the specified instance is valid.
106 /// <para>
107 /// All validators are run for the specified <see cref="RunWhen"/> phase.
108 /// </para>
109 /// </summary>
110 /// <param name="objectInstance">The object instance to be validated (cannot be null).</param>
111 /// <param name="runWhen">Restrict the set returned to the phase specified</param>
112 /// <returns>
113 /// <see langword="true"/> if the specified instance is valid; otherwise, <see langword="false"/>.
114 /// </returns>
115 public bool IsValid(object objectInstance, RunWhen runWhen)
117 if (objectInstance == null) throw new ArgumentNullException("objectInstance");
119 bool isValid = true;
121 ErrorSummary summary = new ErrorSummary();
123 foreach(IValidator validator in GetValidators(objectInstance, runWhen))
125 if (!validator.IsValid(objectInstance))
127 string name = validator.FriendlyName ?? validator.Name;
129 summary.RegisterErrorMessage(name, validator.ErrorMessage);
131 isValid = false;
135 errorPerInstance[objectInstance] = summary;
137 return isValid;
140 /// <summary>
141 /// Gets the registered validators.
142 /// </summary>
143 /// <param name="parentType">Type of the parent.</param>
144 /// <param name="property">The property.</param>
145 /// <returns></returns>
146 public IValidator[] GetValidators(Type parentType, PropertyInfo property)
148 return GetValidators(parentType, property, RunWhen.Everytime);
151 /// <summary>
152 /// Gets the registered validators.
153 /// </summary>
154 /// <param name="parentType">Type of the parent.</param>
155 /// <param name="property">The property.</param>
156 /// <param name="runWhenPhase">The run when phase.</param>
157 /// <returns></returns>
158 public IValidator[] GetValidators(Type parentType, PropertyInfo property, RunWhen runWhenPhase)
160 if (parentType == null) throw new ArgumentNullException("parentType");
161 if (property == null) throw new ArgumentNullException("property");
163 IValidator[] validators = registry.GetValidators(this, parentType, property, runWhenPhase);
165 if (inferValidators && validators.Length == 0)
167 Type defaultValidatorForType = (Type) type2Validator[property.PropertyType];
169 if (defaultValidatorForType != null)
171 validators = new IValidator[] {(IValidator) Activator.CreateInstance(defaultValidatorForType)};
173 validators[0].Initialize(registry, property);
177 Array.Sort(validators, ValidatorComparer.Instance);
179 return validators;
182 /// <summary>
183 /// Gets the error list per instance.
184 /// </summary>
185 /// <param name="instance">The instance.</param>
186 /// <returns></returns>
187 public bool HasErrors(object instance)
189 ErrorSummary summary = GetErrorSummary(instance);
191 if (summary == null) return false;
193 return summary.ErrorsCount != 0;
196 /// <summary>
197 /// Gets the error list per instance.
198 /// </summary>
199 /// <param name="instance">The instance.</param>
200 /// <returns></returns>
201 public ErrorSummary GetErrorSummary(object instance)
203 return errorPerInstance.ContainsKey(instance) ? errorPerInstance[instance] : null;
206 /// <summary>
207 /// Gets the extended properties, which allows <see cref="IValidator"/>
208 /// implementation to store additional information to track state.
209 /// </summary>
210 /// <value>The extended properties.</value>
211 public IDictionary ExtendedProperties
213 get { return extendedProperties; }
216 private IValidator[] GetValidators(object objectInstance, RunWhen runWhen)
218 if (objectInstance == null) throw new ArgumentNullException("objectInstance");
220 IValidator[] validators = registry.GetValidators(this, objectInstance.GetType(), runWhen);
222 Array.Sort(validators, ValidatorComparer.Instance);
224 return validators;
227 private class ValidatorComparer : IComparer
229 private static readonly ValidatorComparer instance = new ValidatorComparer();
231 public int Compare(object x, object y)
233 IValidator left = (IValidator) x;
234 IValidator right = (IValidator) y;
236 return left.ExecutionOrder - right.ExecutionOrder;
239 public static ValidatorComparer Instance
241 get { return instance; }