2 * Namespace: System.Web.UI.WebControls
3 * Class: BaseCompareValidator
6 * Maintainer: gvaish@iitk.ac.in
8 * Contact: <gvaish@iitk.ac.in>
11 * (C) Gaurav Vaish (2001)
15 using System.Collections;
16 using System.Globalization;
18 using System.Text.RegularExpressions;
21 using System.ComponentModel;
23 namespace System.Web.UI.WebControls
25 public abstract class BaseCompareValidator: BaseValidator
27 protected BaseCompareValidator(): base()
31 public static bool CanConvert(string text, ValidationDataType type)
34 return Convert(text, type, out o);
37 [DefaultValue(ValidationDataType.String)]
38 [WebCategory("Behaviour")]
39 [WebSysDescription("RangeValidator_Type")]
40 public ValidationDataType Type
44 object o = ViewState["Type"];
46 return (ValidationDataType)o;
47 return ValidationDataType.String;
51 if(!System.Enum.IsDefined(typeof(ValidationDataType), value))
52 throw new ArgumentException();
53 ViewState["Type"] = value;
57 protected static int CutoffYear
61 return DateTimeFormatInfo.CurrentInfo.Calendar.TwoDigitYearMax;
65 protected static int GetFullYear(int shortYear)
67 int century = DateTime.Today.Year - (DateTime.Today.Year % 100);
68 if(century < CutoffYear)
70 return (shortYear + century);
72 return (shortYear + century - 100);
75 protected override void AddAttributesToRender(HtmlTextWriter writer)
77 base.AddAttributesToRender(writer);
80 writer.AddAttribute("type", PropertyConverter.EnumToString(typeof(ValidationDataType), Type));
81 NumberFormatInfo currInfo = NumberFormatInfo.CurrentInfo;
82 if(Type == ValidationDataType.Double)
84 writer.AddAttribute("decimalchar", currInfo.NumberDecimalSeparator);
87 if(Type == ValidationDataType.Currency)
89 writer.AddAttribute("decimalchar", currInfo.CurrencyDecimalSeparator);
90 string grpSep = currInfo.CurrencyGroupSeparator;
95 writer.AddAttribute("groupchar", grpSep);
96 writer.AddAttribute("digits", currInfo.CurrencyDecimalDigits.ToString(NumberFormatInfo.InvariantInfo));
99 if(Type == ValidationDataType.Date)
101 writer.AddAttribute("cutoffyear", CutoffYear.ToString());
102 writer.AddAttribute("century", ( DateTime.Today.Year - (DateTime.Today.Year % 100) ).ToString());
108 protected override bool DetermineRenderUplevel()
110 if(Type == ValidationDataType.Date && DateTimeFormatInfo.CurrentInfo.Calendar.GetType() != typeof(GregorianCalendar))
114 return base.DetermineRenderUplevel();
120 protected static bool Compare(string leftText, string rightText, ValidationCompareOperator op, ValidationDataType type)
122 object left = null, right = null;
123 if(!Convert(leftText, type, out left))
127 if(op == ValidationCompareOperator.DataTypeCheck)
131 if(!Convert(rightText, type, out right))
135 int compareResult = 0;
138 case ValidationDataType.String:
139 compareResult = ((String)left).CompareTo(right);
141 case ValidationDataType.Integer:
142 compareResult = ((int)left).CompareTo(right);
144 case ValidationDataType.Double:
145 compareResult = ((Double)left).CompareTo(right);
147 case ValidationDataType.Date:
148 compareResult = ((DateTime)left).CompareTo(right);
150 case ValidationDataType.Currency:
151 compareResult = ((Decimal)left).CompareTo(right);
156 case ValidationCompareOperator.Equal:
157 return (compareResult == 0);
158 case ValidationCompareOperator.NotEqual:
159 return (compareResult != 0);
160 case ValidationCompareOperator.GreaterThan:
161 return (compareResult > 0);
162 case ValidationCompareOperator.GreaterThanEqual:
163 return (compareResult >= 0);
164 case ValidationCompareOperator.LessThan:
165 return (compareResult < 0);
166 case ValidationCompareOperator.LessThanEqual:
167 return (compareResult <= 0);
175 protected static string GetDateElementOrder()
177 string pattern = DateTimeFormatInfo.CurrentInfo.ShortDatePattern;
179 //TODO: What are the various possibilities?
180 // I can think of only y*/M*/d*, d*/M*/y*, M*/d*/y*
181 if(pattern.IndexOf('y') < pattern.IndexOf('M'))
185 if(pattern.IndexOf('M') < pattern.IndexOf('d'))
195 protected static bool Convert(string text, ValidationDataType type, out object convertedValue)
197 convertedValue = null;
202 case ValidationDataType.String: convertedValue = text;
204 case ValidationDataType.Integer: convertedValue = Int32.Parse(text, CultureInfo.InvariantCulture);
206 case ValidationDataType.Double:
207 Match matchDouble = Regex.Match(text, @"^\s*([-\+])?(\d+)?(\"
208 + NumberFormatInfo.CurrentInfo.NumberDecimalSeparator
210 if(matchDouble.Success)
212 string sign = (matchDouble.Groups[1].Success ? matchDouble.Groups[1].Value : "+");
213 string decPart = (matchDouble.Groups[2].Success ? matchDouble.Groups[2].Value : "0");
214 string mantissa = (matchDouble.Groups[4].Success ? matchDouble.Groups[4].Value : "0");
215 convertedValue = Double.Parse(sign + decPart + "." + mantissa, CultureInfo.InvariantCulture);
218 case ValidationDataType.Date:
219 if(DateTimeFormatInfo.CurrentInfo.Calendar.GetType() != typeof(GregorianCalendar))
221 convertedValue = DateTime.Parse(text);
224 string order = GetDateElementOrder();
225 int date = 0, mth = 0, year = 0;
226 Match matchDate = Regex.Match(text, @"^\s*((\d{4})|(\d{2}))([\.\/-])(\d{1,2})\4(\d{1,2})\s*$");
227 if(matchDate.Success && order == "ymd")
229 date = Int32.Parse(matchDate.Groups[6].Value, CultureInfo.InvariantCulture);
230 mth = Int32.Parse(matchDate.Groups[5].Value, CultureInfo.InvariantCulture);
231 year = Int32.Parse((matchDate.Groups[2].Success ? matchDate.Groups[2].Value : matchDate.Groups[3].Value), CultureInfo.InvariantCulture);
234 matchDate = Regex.Match(text, @"^\s*(\d{1,2})([\.\/-])(\d{1,2})\2((\d{4}|\d{2}))\s*$");
235 if(matchDate.Success)
239 date = Int32.Parse(matchDate.Groups[1].Value, CultureInfo.InvariantCulture);
240 mth = Int32.Parse(matchDate.Groups[3].Value, CultureInfo.InvariantCulture);
241 year = Int32.Parse((matchDate.Groups[5].Success ? matchDate.Groups[5].Value : matchDate.Groups[6].Value), CultureInfo.InvariantCulture);
245 date = Int32.Parse(matchDate.Groups[3].Value, CultureInfo.InvariantCulture);
246 mth = Int32.Parse(matchDate.Groups[1].Value, CultureInfo.InvariantCulture);
247 year = Int32.Parse((matchDate.Groups[5].Success ? matchDate.Groups[5].Value : matchDate.Groups[6].Value), CultureInfo.InvariantCulture);
251 year = (year < 100 ? GetFullYear(year) : year);
252 if(matchDate.Success && date!=0 && mth!=0 && year!=0)
254 convertedValue = new DateTime(year, mth, date);
257 case ValidationDataType.Currency:
258 string decSep = NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator;
259 string grpSep = NumberFormatInfo.CurrentInfo.CurrencyGroupSeparator;
260 int decDig = NumberFormatInfo.CurrentInfo.CurrencyDecimalDigits;
261 if(grpSep[0] == 0xA0)
265 string[] patternArray = new string[5];
266 patternArray[0] = "^\\s*([-\\+])?(((\\d+)\\";
267 patternArray[1] = grpSep;
268 patternArray[2] = @")*)(\d+)";
271 string[] decPattern = new string[5];
272 decPattern[0] = "(\\";
273 decPattern[1] = decSep;
274 decPattern[2] = @"(\d{1,";
275 decPattern[3] = decDig.ToString(NumberFormatInfo.InvariantInfo);
276 decPattern[4] = @"}))";
277 patternArray[3] = String.Concat(decPattern);
281 patternArray[3] = String.Empty;
283 patternArray[4] = @"?\s*$";
284 Match matchCurrency = Regex.Match(text, String.Concat(patternArray));
285 if(matchCurrency.Success)
287 StringBuilder sb = new StringBuilder();
288 sb.Append(matchCurrency.Groups[1]);
289 CaptureCollection cc = matchCurrency.Groups[4].Captures;
290 foreach(IEnumerable current in cc)
292 sb.Append((Capture)current);
294 sb.Append(matchCurrency.Groups[5]);
298 sb.Append(matchCurrency.Groups[7]);
300 convertedValue = Decimal.Parse(sb.ToString(), CultureInfo.InvariantCulture);
306 convertedValue = null;
308 return (convertedValue != null);