Adding the following validators:
[castle.git] / Components / General / Validator / Castle.Components.Validator / ValidatorRunner.cs
blobcf02a9003477caf7d30d516e181c66a781a35844
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.Reflection;
21 /// <summary>
22 /// Coordinates the gathering and execution of validators.
23 /// <seealso cref="IValidatorRegistry"/>
24 /// </summary>
25 /// <example>
26 /// ValidatorRunner runner = new ValidatorRunner(new CachedValidationRegistry());
27 ///
28 /// if (!runner.IsValid(customer))
29 /// {
30 /// // do something as the Customer instance is not valid
31 /// }
32 /// </example>
33 public class ValidatorRunner
35 private readonly static IDictionary type2Validator;
36 private readonly IDictionary extendedProperties = new Hashtable();
37 private readonly bool inferValidators;
38 private readonly IDictionary errorPerInstance;
39 private readonly IValidatorRegistry registry;
41 static ValidatorRunner()
43 type2Validator = new Hashtable();
44 type2Validator[typeof(Int16)] = typeof(IntegerValidator);
45 type2Validator[typeof(Int32)] = typeof(IntegerValidator);
46 type2Validator[typeof(Int64)] = typeof(IntegerValidator);
47 type2Validator[typeof(decimal)] = typeof(DecimalValidator);
48 type2Validator[typeof(Single)] = typeof(SingleValidator);
49 type2Validator[typeof(double)] = typeof(DoubleValidator);
50 type2Validator[typeof(DateTime)] = typeof(DateTimeValidator);
53 public IDictionary ExtendedProperties
55 get { return extendedProperties; }
58 /// <summary>
59 /// Initializes a new instance of the <see cref="ValidatorRunner"/> class.
60 /// </summary>
61 /// <param name="registry">The instance registry.</param>
62 public ValidatorRunner(IValidatorRegistry registry) : this(true, registry)
66 /// <summary>
67 /// Initializes a new instance of the <see cref="ValidatorRunner"/> class.
68 /// </summary>
69 /// <param name="inferValidators">if <c>true</c>, the runner will try
70 /// to infer un-declared validators based on property types</param>
71 /// <param name="registry">The registry.</param>
72 public ValidatorRunner(bool inferValidators, IValidatorRegistry registry)
74 if (registry == null) throw new ArgumentNullException("registry");
76 errorPerInstance = new Hashtable();
78 this.inferValidators = inferValidators;
79 this.registry = registry;
82 /// <summary>
83 /// Determines whether the specified instance is valid.
84 /// <para>
85 /// All validators are run.
86 /// </para>
87 /// </summary>
88 /// <param name="objectInstance">The object instance to be validated (cannot be null).</param>
89 /// <returns>
90 /// <see langword="true"/> if the specified obj is valid; otherwise, <see langword="false"/>.
91 /// </returns>
92 public bool IsValid(object objectInstance)
94 return IsValid(objectInstance, RunWhen.Everytime);
97 /// <summary>
98 /// Determines whether the specified instance is valid.
99 /// <para>
100 /// All validators are run for the specified <see cref="RunWhen"/> phase.
101 /// </para>
102 /// </summary>
103 /// <param name="objectInstance">The object instance to be validated (cannot be null).</param>
104 /// <param name="runWhen">Restrict the set returned to the phase specified</param>
105 /// <returns>
106 /// <see langword="true"/> if the specified instance is valid; otherwise, <see langword="false"/>.
107 /// </returns>
108 public bool IsValid(object objectInstance, RunWhen runWhen)
110 if (objectInstance == null) throw new ArgumentNullException("objectInstance");
112 bool isValid = true;
114 ErrorSummary summary = new ErrorSummary();
116 foreach(IValidator validator in GetValidators(objectInstance, runWhen))
118 if (!validator.IsValid(objectInstance))
120 summary.RegisterErrorMessage(validator.Name, validator.ErrorMessage);
122 isValid = false;
126 errorPerInstance[objectInstance] = summary;
128 return isValid;
131 /// <summary>
132 /// Gets the registered validators.
133 /// </summary>
134 /// <param name="parentType">Type of the parent.</param>
135 /// <param name="property">The property.</param>
136 /// <returns></returns>
137 public IValidator[] GetValidators(Type parentType, PropertyInfo property)
139 return GetValidators(parentType, property, RunWhen.Everytime);
142 /// <summary>
143 /// Gets the registered validators.
144 /// </summary>
145 /// <param name="parentType">Type of the parent.</param>
146 /// <param name="property">The property.</param>
147 /// <param name="runWhenPhase">The run when phase.</param>
148 /// <returns></returns>
149 public IValidator[] GetValidators(Type parentType, PropertyInfo property, RunWhen runWhenPhase)
151 if (parentType == null) throw new ArgumentNullException("parentType");
152 if (property == null) throw new ArgumentNullException("property");
154 IValidator[] validators = registry.GetValidators(this, parentType, property, runWhenPhase);
156 if (inferValidators && validators.Length == 0)
158 Type defaultValidatorForType = (Type) type2Validator[property.PropertyType];
160 if (defaultValidatorForType != null)
162 validators = new IValidator[] { (IValidator) Activator.CreateInstance(defaultValidatorForType) };
164 validators[0].Initialize(property);
168 Array.Sort(validators, ValidatorComparer.Instance);
170 return validators;
173 /// <summary>
174 /// Gets the error list per instance.
175 /// </summary>
176 /// <param name="instance">The instance.</param>
177 /// <returns></returns>
178 public bool HasErrors(object instance)
180 ErrorSummary summary = (ErrorSummary) errorPerInstance[instance];
182 if (summary == null) return false;
184 return summary.ErrorsCount != 0;
187 /// <summary>
188 /// Gets the error list per instance.
189 /// </summary>
190 /// <param name="instance">The instance.</param>
191 /// <returns></returns>
192 public ErrorSummary GetErrorSummary(object instance)
194 return (ErrorSummary) errorPerInstance[instance];
197 private IValidator[] GetValidators(object objectInstance, RunWhen runWhen)
199 if (objectInstance == null) throw new ArgumentNullException("objectInstance");
201 IValidator[] validators = registry.GetValidators(this, objectInstance.GetType(), runWhen);
203 Array.Sort(validators, ValidatorComparer.Instance);
205 return validators;
208 class ValidatorComparer : IComparer
210 private readonly static ValidatorComparer instance = new ValidatorComparer();
212 public int Compare(object x, object y)
214 IValidator left = (IValidator) x;
215 IValidator right = (IValidator) y;
217 return left.ExecutionOrder - right.ExecutionOrder;
220 public static ValidatorComparer Instance
222 get { return instance; }