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'))
192 static bool ConvertDate (string text, ValidationDataType type, ref object convertedValue)
194 //Console.WriteLine (DateTimeFormatInfo.CurrentInfo.Calendar.GetType ());
195 // FIXME: sometime, somehow, the condition is true even when GetType () says
196 // it's a GregorianCalendar.
197 if (DateTimeFormatInfo.CurrentInfo.Calendar.GetType () != typeof (GregorianCalendar)) {
198 convertedValue = DateTime.Parse (text);
202 string order = GetDateElementOrder ();
203 int date = 0, mth = 0, year = 0;
204 string dateStr = null;
205 string mthStr = null;
206 string yearStr = null;
207 Match match = Regex.Match (text, @"^\s*((\d{4})|(\d{2}))([\.\/-])(\d{1,2})\4(\d{1,2})\s*$");
208 if (match.Success || order == "ymd") {
209 dateStr = match.Groups [6].Value;
210 mthStr = match.Groups [5].Value;
211 if (match.Groups [2].Success)
212 yearStr = match.Groups [2].Value;
214 yearStr = match.Groups [3].Value;
216 match = Regex.Match(text, @"^\s*(\d{1,2})([\.\/-])(\d{1,2})\2((\d{4}|\d{2}))\s*$");
220 if (order == "dmy") {
221 dateStr = match.Groups [1].Value;
222 mthStr = match.Groups [3].Value;
223 if (match.Groups [5].Success)
224 yearStr = match.Groups [5].Value;
226 yearStr = match.Groups [6].Value;
227 } else if (order == "mdy") {
228 dateStr = match.Groups [3].Value;
229 mthStr = match.Groups [1].Value;
230 if (match.Groups [5].Success)
231 yearStr = match.Groups [5].Value;
233 yearStr = match.Groups [6].Value;
237 if (dateStr == null || mthStr == null || yearStr == null) {
241 CultureInfo inv = CultureInfo.InvariantCulture;
242 date = Int32.Parse (dateStr, inv);
243 mth = Int32.Parse (mthStr, inv);
244 year = Int32.Parse (yearStr, inv);
245 year = (year < 100 ? GetFullYear (year) : year);
246 if (date != 0 && mth != 0 && year != 0) {
247 convertedValue = new DateTime (year, mth, date);
254 static bool ConvertDouble (string text, ValidationDataType type, ref object convertedValue)
256 Match match = Regex.Match (text, @"^\s*([-\+])?(\d+)?(\" +
257 NumberFormatInfo.CurrentInfo.NumberDecimalSeparator +
263 string sign = (match.Groups [1].Success ? match.Groups [1].Value : "+");
264 string decPart = (match.Groups [2].Success ? match.Groups [2].Value : "0");
265 string mantissa = (match.Groups [4].Success ? match.Groups [4].Value : "0");
266 string num = sign + decPart + "." + mantissa;
267 convertedValue = Double.Parse (num, CultureInfo.InvariantCulture);
271 static bool ConvertCurrency (string text, ValidationDataType type, ref object convertedValue)
273 string decSep = NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator;
274 string grpSep = NumberFormatInfo.CurrentInfo.CurrencyGroupSeparator;
275 int decDig = NumberFormatInfo.CurrentInfo.CurrencyDecimalDigits;
276 if (grpSep [0] == 0xA0)
279 string [] patternArray = new string [5];
280 patternArray [0] = "^\\s*([-\\+])?(((\\d+)\\";
281 patternArray [1] = grpSep;
282 patternArray [2] = @")*)(\d+)";
284 string [] decPattern = new string [5];
285 decPattern [0] = "(\\";
286 decPattern [1] = decSep;
287 decPattern [2] = @"(\d{1,";
288 decPattern [3] = decDig.ToString (NumberFormatInfo.InvariantInfo);
289 decPattern [4] = @"}))";
290 patternArray [3] = String.Concat (decPattern);
293 patternArray [3] = String.Empty;
296 patternArray [4] = @"?\s*$";
297 Match match = Regex.Match (text, String.Concat (patternArray));
301 StringBuilder sb = new StringBuilder ();
302 sb.Append (match.Groups [1]);
303 CaptureCollection cc = match.Groups [4].Captures;
304 foreach (IEnumerable current in cc)
305 sb.Append ((Capture) current);
307 sb.Append (match.Groups [5]);
310 sb.Append (match.Groups [7]);
313 convertedValue = Decimal.Parse (sb.ToString (), CultureInfo.InvariantCulture);
320 protected static bool Convert (string text, ValidationDataType type, out object convertedValue)
322 CultureInfo inv = CultureInfo.InvariantCulture;
323 convertedValue = null;
326 case ValidationDataType.String:
327 convertedValue = text;
329 case ValidationDataType.Integer:
330 convertedValue = Int32.Parse (text, inv);
332 case ValidationDataType.Double:
333 return ConvertDouble (text, type, ref convertedValue);
334 case ValidationDataType.Date:
335 return ConvertDate (text, type, ref convertedValue);
336 case ValidationDataType.Currency:
337 return ConvertCurrency (text, type, ref convertedValue);
339 } catch (Exception) {
340 convertedValue = null;
343 return (convertedValue != null);