3 // Permission is hereby granted, free of charge, to any person obtaining
4 // a copy of this software and associated documentation files (the
5 // "Software"), to deal in the Software without restriction, including
6 // without limitation the rights to use, copy, modify, merge, publish,
7 // distribute, sublicense, and/or sell copies of the Software, and to
8 // permit persons to whom the Software is furnished to do so, subject to
9 // the following conditions:
11 // The above copyright notice and this permission notice shall be
12 // included in all copies or substantial portions of the Software.
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 * Namespace: System.Web.UI.WebControls
24 * Class: BaseCompareValidator
26 * Author: Gaurav Vaish
27 * Maintainer: gvaish@iitk.ac.in
29 * Contact: <gvaish@iitk.ac.in>
32 * (C) Gaurav Vaish (2001)
36 using System
.Collections
;
37 using System
.Globalization
;
39 using System
.Text
.RegularExpressions
;
42 using System
.ComponentModel
;
44 namespace System
.Web
.UI
.WebControls
46 public abstract class BaseCompareValidator
: BaseValidator
48 protected BaseCompareValidator(): base()
52 public static bool CanConvert(string text
, ValidationDataType type
)
55 return Convert(text
, type
, out o
);
58 [DefaultValue(ValidationDataType
.String
)]
59 [WebCategory("Behavior")]
60 [WebSysDescription("RangeValidator_Type")]
61 public ValidationDataType Type
65 object o
= ViewState
["Type"];
67 return (ValidationDataType
)o
;
68 return ValidationDataType
.String
;
72 if(!System
.Enum
.IsDefined(typeof(ValidationDataType
), value))
73 throw new ArgumentException();
74 ViewState
["Type"] = value;
78 protected static int CutoffYear
82 return DateTimeFormatInfo
.CurrentInfo
.Calendar
.TwoDigitYearMax
;
86 protected static int GetFullYear(int shortYear
)
88 int century
= DateTime
.Today
.Year
- (DateTime
.Today
.Year
% 100);
89 if(century
< CutoffYear
)
91 return (shortYear
+ century
);
93 return (shortYear
+ century
- 100);
96 protected override void AddAttributesToRender(HtmlTextWriter writer
)
98 base.AddAttributesToRender(writer
);
101 writer
.AddAttribute("type", PropertyConverter
.EnumToString(typeof(ValidationDataType
), Type
));
102 NumberFormatInfo currInfo
= NumberFormatInfo
.CurrentInfo
;
103 if(Type
== ValidationDataType
.Double
)
105 writer
.AddAttribute("decimalchar", currInfo
.NumberDecimalSeparator
);
108 if(Type
== ValidationDataType
.Currency
)
110 writer
.AddAttribute("decimalchar", currInfo
.CurrencyDecimalSeparator
);
111 string grpSep
= currInfo
.CurrencyGroupSeparator
;
112 if(grpSep
[0] == 0xA0)
116 writer
.AddAttribute("groupchar", grpSep
);
117 writer
.AddAttribute("digits", currInfo
.CurrencyDecimalDigits
.ToString(NumberFormatInfo
.InvariantInfo
));
120 if(Type
== ValidationDataType
.Date
)
122 writer
.AddAttribute("cutoffyear", CutoffYear
.ToString());
123 writer
.AddAttribute("century", ( DateTime
.Today
.Year
- (DateTime
.Today
.Year
% 100) ).ToString());
129 protected override bool DetermineRenderUplevel()
131 if(Type
== ValidationDataType
.Date
&& DateTimeFormatInfo
.CurrentInfo
.Calendar
.GetType() != typeof(GregorianCalendar
))
135 return base.DetermineRenderUplevel();
141 protected static bool Compare(string leftText
, string rightText
, ValidationCompareOperator op
, ValidationDataType type
)
143 object left
= null, right
= null;
144 if(!Convert(leftText
, type
, out left
))
148 if(op
== ValidationCompareOperator
.DataTypeCheck
)
152 if(!Convert(rightText
, type
, out right
))
156 int compareResult
= 0;
159 case ValidationDataType
.String
:
160 compareResult
= ((String
)left
).CompareTo(right
);
162 case ValidationDataType
.Integer
:
163 compareResult
= ((int)left
).CompareTo(right
);
165 case ValidationDataType
.Double
:
166 compareResult
= ((Double
)left
).CompareTo(right
);
168 case ValidationDataType
.Date
:
169 compareResult
= ((DateTime
)left
).CompareTo(right
);
171 case ValidationDataType
.Currency
:
172 compareResult
= ((Decimal
)left
).CompareTo(right
);
177 case ValidationCompareOperator
.Equal
:
178 return (compareResult
== 0);
179 case ValidationCompareOperator
.NotEqual
:
180 return (compareResult
!= 0);
181 case ValidationCompareOperator
.GreaterThan
:
182 return (compareResult
> 0);
183 case ValidationCompareOperator
.GreaterThanEqual
:
184 return (compareResult
>= 0);
185 case ValidationCompareOperator
.LessThan
:
186 return (compareResult
< 0);
187 case ValidationCompareOperator
.LessThanEqual
:
188 return (compareResult
<= 0);
196 protected static string GetDateElementOrder()
198 string pattern
= DateTimeFormatInfo
.CurrentInfo
.ShortDatePattern
;
200 //TODO: What are the various possibilities?
201 // I can think of only y*/M*/d*, d*/M*/y*, M*/d*/y*
202 if(pattern
.IndexOf('y') < pattern
.IndexOf('M'))
206 if(pattern
.IndexOf('M') < pattern
.IndexOf('d'))
213 static bool ConvertDate (string text
, ValidationDataType type
, ref object convertedValue
)
215 //Console.WriteLine (DateTimeFormatInfo.CurrentInfo.Calendar.GetType ());
216 // FIXME: sometime, somehow, the condition is true even when GetType () says
217 // it's a GregorianCalendar.
218 if (DateTimeFormatInfo
.CurrentInfo
.Calendar
.GetType () != typeof (GregorianCalendar
)) {
219 convertedValue
= DateTime
.Parse (text
);
223 string order
= GetDateElementOrder ();
224 int date
= 0, mth
= 0, year
= 0;
225 string dateStr
= null;
226 string mthStr
= null;
227 string yearStr
= null;
228 Match match
= Regex
.Match (text
, @"^\s*((\d{4})|(\d{2}))([\.\/-])(\d{1,2})\4(\d{1,2})\s*$");
229 if (match
.Success
|| order
== "ymd") {
230 dateStr
= match
.Groups
[6].Value
;
231 mthStr
= match
.Groups
[5].Value
;
232 if (match
.Groups
[2].Success
)
233 yearStr
= match
.Groups
[2].Value
;
235 yearStr
= match
.Groups
[3].Value
;
237 match
= Regex
.Match(text
, @"^\s*(\d{1,2})([\.\/-])(\d{1,2})\2((\d{4}|\d{2}))\s*$");
241 if (order
== "dmy") {
242 dateStr
= match
.Groups
[1].Value
;
243 mthStr
= match
.Groups
[3].Value
;
244 if (match
.Groups
[5].Success
)
245 yearStr
= match
.Groups
[5].Value
;
247 yearStr
= match
.Groups
[6].Value
;
248 } else if (order
== "mdy") {
249 dateStr
= match
.Groups
[3].Value
;
250 mthStr
= match
.Groups
[1].Value
;
251 if (match
.Groups
[5].Success
)
252 yearStr
= match
.Groups
[5].Value
;
254 yearStr
= match
.Groups
[6].Value
;
258 if (dateStr
== null || mthStr
== null || yearStr
== null) {
262 CultureInfo inv
= CultureInfo
.InvariantCulture
;
263 date
= Int32
.Parse (dateStr
, inv
);
264 mth
= Int32
.Parse (mthStr
, inv
);
265 year
= Int32
.Parse (yearStr
, inv
);
266 year
= (year
< 100 ? GetFullYear (year
) : year
);
267 if (date
!= 0 && mth
!= 0 && year
!= 0) {
268 convertedValue
= new DateTime (year
, mth
, date
);
275 static bool ConvertDouble (string text
, ValidationDataType type
, ref object convertedValue
)
277 Match match
= Regex
.Match (text
, @"^\s*([-\+])?(\d+)?(\" +
278 NumberFormatInfo
.CurrentInfo
.NumberDecimalSeparator
+
284 string sign
= (match
.Groups
[1].Success
? match
.Groups
[1].Value
: "+");
285 string decPart
= (match
.Groups
[2].Success
? match
.Groups
[2].Value
: "0");
286 string mantissa
= (match
.Groups
[4].Success
? match
.Groups
[4].Value
: "0");
287 string num
= sign
+ decPart
+ "." + mantissa
;
288 convertedValue
= Double
.Parse (num
, CultureInfo
.InvariantCulture
);
292 static bool ConvertCurrency (string text
, ValidationDataType type
, ref object convertedValue
)
294 string decSep
= NumberFormatInfo
.CurrentInfo
.CurrencyDecimalSeparator
;
295 string grpSep
= NumberFormatInfo
.CurrentInfo
.CurrencyGroupSeparator
;
296 int decDig
= NumberFormatInfo
.CurrentInfo
.CurrencyDecimalDigits
;
297 if (grpSep
[0] == 0xA0)
300 string [] patternArray
= new string [5];
301 patternArray
[0] = "^\\s*([-\\+])?(((\\d+)\\";
302 patternArray
[1] = grpSep
;
303 patternArray
[2] = @")*)(\d+)";
305 string [] decPattern
= new string [5];
306 decPattern
[0] = "(\\";
307 decPattern
[1] = decSep
;
308 decPattern
[2] = @"(\d{1,";
309 decPattern
[3] = decDig
.ToString (NumberFormatInfo
.InvariantInfo
);
310 decPattern
[4] = @"}))";
311 patternArray
[3] = String
.Concat (decPattern
);
314 patternArray
[3] = String
.Empty
;
317 patternArray
[4] = @"?\s*$";
318 Match match
= Regex
.Match (text
, String
.Concat (patternArray
));
322 StringBuilder sb
= new StringBuilder ();
323 sb
.Append (match
.Groups
[1]);
324 CaptureCollection cc
= match
.Groups
[4].Captures
;
325 foreach (IEnumerable current
in cc
)
326 sb
.Append ((Capture
) current
);
328 sb
.Append (match
.Groups
[5]);
331 sb
.Append (match
.Groups
[7]);
334 convertedValue
= Decimal
.Parse (sb
.ToString (), CultureInfo
.InvariantCulture
);
341 protected static bool Convert (string text
, ValidationDataType type
, out object convertedValue
)
343 CultureInfo inv
= CultureInfo
.InvariantCulture
;
344 convertedValue
= null;
347 case ValidationDataType
.String
:
348 convertedValue
= text
;
350 case ValidationDataType
.Integer
:
351 convertedValue
= Int32
.Parse (text
, inv
);
353 case ValidationDataType
.Double
:
354 return ConvertDouble (text
, type
, ref convertedValue
);
355 case ValidationDataType
.Date
:
356 return ConvertDate (text
, type
, ref convertedValue
);
357 case ValidationDataType
.Currency
:
358 return ConvertCurrency (text
, type
, ref convertedValue
);
360 } catch (Exception
) {
361 convertedValue
= null;
364 return (convertedValue
!= null);