BaseCompareValidator.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. //
  2. // Permission is hereby granted, free of charge, to any person obtaining
  3. // a copy of this software and associated documentation files (the
  4. // "Software"), to deal in the Software without restriction, including
  5. // without limitation the rights to use, copy, modify, merge, publish,
  6. // distribute, sublicense, and/or sell copies of the Software, and to
  7. // permit persons to whom the Software is furnished to do so, subject to
  8. // the following conditions:
  9. //
  10. // The above copyright notice and this permission notice shall be
  11. // included in all copies or substantial portions of the Software.
  12. //
  13. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  15. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  17. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  18. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  19. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  20. //
  21. /**
  22. * Namespace: System.Web.UI.WebControls
  23. * Class: BaseCompareValidator
  24. *
  25. * Author: Gaurav Vaish
  26. * Maintainer: [email protected]
  27. * Implementation: yes
  28. * Contact: <[email protected]>
  29. * Status: 100%
  30. *
  31. * (C) Gaurav Vaish (2001)
  32. */
  33. using System;
  34. using System.Collections;
  35. using System.Globalization;
  36. using System.Text;
  37. using System.Text.RegularExpressions;
  38. using System.Web;
  39. using System.Web.UI;
  40. using System.ComponentModel;
  41. namespace System.Web.UI.WebControls
  42. {
  43. public abstract class BaseCompareValidator: BaseValidator
  44. {
  45. protected BaseCompareValidator(): base()
  46. {
  47. }
  48. public static bool CanConvert(string text, ValidationDataType type)
  49. {
  50. object o = null;
  51. return Convert(text, type, out o);
  52. }
  53. [DefaultValue(ValidationDataType.String)]
  54. [WebCategory("Behaviour")]
  55. [WebSysDescription("RangeValidator_Type")]
  56. public ValidationDataType Type
  57. {
  58. get
  59. {
  60. object o = ViewState["Type"];
  61. if(o!=null)
  62. return (ValidationDataType)o;
  63. return ValidationDataType.String;
  64. }
  65. set
  66. {
  67. if(!System.Enum.IsDefined(typeof(ValidationDataType), value))
  68. throw new ArgumentException();
  69. ViewState["Type"] = value;
  70. }
  71. }
  72. protected static int CutoffYear
  73. {
  74. get
  75. {
  76. return DateTimeFormatInfo.CurrentInfo.Calendar.TwoDigitYearMax;
  77. }
  78. }
  79. protected static int GetFullYear(int shortYear)
  80. {
  81. int century = DateTime.Today.Year - (DateTime.Today.Year % 100);
  82. if(century < CutoffYear)
  83. {
  84. return (shortYear + century);
  85. }
  86. return (shortYear + century - 100);
  87. }
  88. protected override void AddAttributesToRender(HtmlTextWriter writer)
  89. {
  90. base.AddAttributesToRender(writer);
  91. if(RenderUplevel)
  92. {
  93. writer.AddAttribute("type", PropertyConverter.EnumToString(typeof(ValidationDataType), Type));
  94. NumberFormatInfo currInfo = NumberFormatInfo.CurrentInfo;
  95. if(Type == ValidationDataType.Double)
  96. {
  97. writer.AddAttribute("decimalchar", currInfo.NumberDecimalSeparator);
  98. return;
  99. }
  100. if(Type == ValidationDataType.Currency)
  101. {
  102. writer.AddAttribute("decimalchar", currInfo.CurrencyDecimalSeparator);
  103. string grpSep = currInfo.CurrencyGroupSeparator;
  104. if(grpSep[0] == 0xA0)
  105. {
  106. grpSep = " ";
  107. }
  108. writer.AddAttribute("groupchar", grpSep);
  109. writer.AddAttribute("digits", currInfo.CurrencyDecimalDigits.ToString(NumberFormatInfo.InvariantInfo));
  110. return;
  111. }
  112. if(Type == ValidationDataType.Date)
  113. {
  114. writer.AddAttribute("cutoffyear", CutoffYear.ToString());
  115. writer.AddAttribute("century", ( DateTime.Today.Year - (DateTime.Today.Year % 100) ).ToString());
  116. return;
  117. }
  118. }
  119. }
  120. protected override bool DetermineRenderUplevel()
  121. {
  122. if(Type == ValidationDataType.Date && DateTimeFormatInfo.CurrentInfo.Calendar.GetType() != typeof(GregorianCalendar))
  123. {
  124. return false;
  125. }
  126. return base.DetermineRenderUplevel();
  127. }
  128. /// <summary>
  129. /// Undocumented
  130. /// </summary>
  131. protected static bool Compare(string leftText, string rightText, ValidationCompareOperator op, ValidationDataType type)
  132. {
  133. object left = null, right = null;
  134. if(!Convert(leftText, type, out left))
  135. {
  136. return false;
  137. }
  138. if(op == ValidationCompareOperator.DataTypeCheck)
  139. {
  140. return true;
  141. }
  142. if(!Convert(rightText, type, out right))
  143. {
  144. return true;
  145. }
  146. int compareResult = 0;
  147. switch(type)
  148. {
  149. case ValidationDataType.String:
  150. compareResult = ((String)left).CompareTo(right);
  151. break;
  152. case ValidationDataType.Integer:
  153. compareResult = ((int)left).CompareTo(right);
  154. break;
  155. case ValidationDataType.Double:
  156. compareResult = ((Double)left).CompareTo(right);
  157. break;
  158. case ValidationDataType.Date:
  159. compareResult = ((DateTime)left).CompareTo(right);
  160. break;
  161. case ValidationDataType.Currency:
  162. compareResult = ((Decimal)left).CompareTo(right);
  163. break;
  164. }
  165. switch(op)
  166. {
  167. case ValidationCompareOperator.Equal:
  168. return (compareResult == 0);
  169. case ValidationCompareOperator.NotEqual:
  170. return (compareResult != 0);
  171. case ValidationCompareOperator.GreaterThan:
  172. return (compareResult > 0);
  173. case ValidationCompareOperator.GreaterThanEqual:
  174. return (compareResult >= 0);
  175. case ValidationCompareOperator.LessThan:
  176. return (compareResult < 0);
  177. case ValidationCompareOperator.LessThanEqual:
  178. return (compareResult <= 0);
  179. }
  180. return false;
  181. }
  182. /// <summary>
  183. /// Undocumented
  184. /// </summary>
  185. protected static string GetDateElementOrder()
  186. {
  187. string pattern = DateTimeFormatInfo.CurrentInfo.ShortDatePattern;
  188. //TODO: What are the various possibilities?
  189. // I can think of only y*/M*/d*, d*/M*/y*, M*/d*/y*
  190. if(pattern.IndexOf('y') < pattern.IndexOf('M'))
  191. {
  192. return "ymd";
  193. }
  194. if(pattern.IndexOf('M') < pattern.IndexOf('d'))
  195. {
  196. return "mdy";
  197. }
  198. return "dmy";
  199. }
  200. static bool ConvertDate (string text, ValidationDataType type, ref object convertedValue)
  201. {
  202. //Console.WriteLine (DateTimeFormatInfo.CurrentInfo.Calendar.GetType ());
  203. // FIXME: sometime, somehow, the condition is true even when GetType () says
  204. // it's a GregorianCalendar.
  205. if (DateTimeFormatInfo.CurrentInfo.Calendar.GetType () != typeof (GregorianCalendar)) {
  206. convertedValue = DateTime.Parse (text);
  207. return true;
  208. }
  209. string order = GetDateElementOrder ();
  210. int date = 0, mth = 0, year = 0;
  211. string dateStr = null;
  212. string mthStr = null;
  213. string yearStr = null;
  214. Match match = Regex.Match (text, @"^\s*((\d{4})|(\d{2}))([\.\/-])(\d{1,2})\4(\d{1,2})\s*$");
  215. if (match.Success || order == "ymd") {
  216. dateStr = match.Groups [6].Value;
  217. mthStr = match.Groups [5].Value;
  218. if (match.Groups [2].Success)
  219. yearStr = match.Groups [2].Value;
  220. else
  221. yearStr = match.Groups [3].Value;
  222. } else {
  223. match = Regex.Match(text, @"^\s*(\d{1,2})([\.\/-])(\d{1,2})\2((\d{4}|\d{2}))\s*$");
  224. if (!match.Success)
  225. return false;
  226. if (order == "dmy") {
  227. dateStr = match.Groups [1].Value;
  228. mthStr = match.Groups [3].Value;
  229. if (match.Groups [5].Success)
  230. yearStr = match.Groups [5].Value;
  231. else
  232. yearStr = match.Groups [6].Value;
  233. } else if (order == "mdy") {
  234. dateStr = match.Groups [3].Value;
  235. mthStr = match.Groups [1].Value;
  236. if (match.Groups [5].Success)
  237. yearStr = match.Groups [5].Value;
  238. else
  239. yearStr = match.Groups [6].Value;
  240. }
  241. }
  242. if (dateStr == null || mthStr == null || yearStr == null) {
  243. return false;
  244. }
  245. CultureInfo inv = CultureInfo.InvariantCulture;
  246. date = Int32.Parse (dateStr, inv);
  247. mth = Int32.Parse (mthStr, inv);
  248. year = Int32.Parse (yearStr, inv);
  249. year = (year < 100 ? GetFullYear (year) : year);
  250. if (date != 0 && mth != 0 && year != 0) {
  251. convertedValue = new DateTime (year, mth, date);
  252. return true;
  253. }
  254. return false;
  255. }
  256. static bool ConvertDouble (string text, ValidationDataType type, ref object convertedValue)
  257. {
  258. Match match = Regex.Match (text, @"^\s*([-\+])?(\d+)?(\" +
  259. NumberFormatInfo.CurrentInfo.NumberDecimalSeparator +
  260. @"(\d+))?\s*$");
  261. if (!match.Success)
  262. return false;
  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);
  268. return true;
  269. }
  270. static bool ConvertCurrency (string text, ValidationDataType type, ref object convertedValue)
  271. {
  272. string decSep = NumberFormatInfo.CurrentInfo.CurrencyDecimalSeparator;
  273. string grpSep = NumberFormatInfo.CurrentInfo.CurrencyGroupSeparator;
  274. int decDig = NumberFormatInfo.CurrentInfo.CurrencyDecimalDigits;
  275. if (grpSep [0] == 0xA0)
  276. grpSep = " ";
  277. string [] patternArray = new string [5];
  278. patternArray [0] = "^\\s*([-\\+])?(((\\d+)\\";
  279. patternArray [1] = grpSep;
  280. patternArray [2] = @")*)(\d+)";
  281. if (decDig > 0) {
  282. string [] decPattern = new string [5];
  283. decPattern [0] = "(\\";
  284. decPattern [1] = decSep;
  285. decPattern [2] = @"(\d{1,";
  286. decPattern [3] = decDig.ToString (NumberFormatInfo.InvariantInfo);
  287. decPattern [4] = @"}))";
  288. patternArray [3] = String.Concat (decPattern);
  289. } else {
  290. patternArray [3] = String.Empty;
  291. }
  292. patternArray [4] = @"?\s*$";
  293. Match match = Regex.Match (text, String.Concat (patternArray));
  294. if (!match.Success)
  295. return false;
  296. StringBuilder sb = new StringBuilder ();
  297. sb.Append (match.Groups [1]);
  298. CaptureCollection cc = match.Groups [4].Captures;
  299. foreach (IEnumerable current in cc)
  300. sb.Append ((Capture) current);
  301. sb.Append (match.Groups [5]);
  302. if (decDig > 0) {
  303. sb.Append (".");
  304. sb.Append (match.Groups [7]);
  305. }
  306. convertedValue = Decimal.Parse (sb.ToString (), CultureInfo.InvariantCulture);
  307. return true;
  308. }
  309. /// <summary>
  310. /// Undocumented
  311. /// </summary>
  312. protected static bool Convert (string text, ValidationDataType type, out object convertedValue)
  313. {
  314. CultureInfo inv = CultureInfo.InvariantCulture;
  315. convertedValue = null;
  316. try {
  317. switch(type) {
  318. case ValidationDataType.String:
  319. convertedValue = text;
  320. break;
  321. case ValidationDataType.Integer:
  322. convertedValue = Int32.Parse (text, inv);
  323. break;
  324. case ValidationDataType.Double:
  325. return ConvertDouble (text, type, ref convertedValue);
  326. case ValidationDataType.Date:
  327. return ConvertDate (text, type, ref convertedValue);
  328. case ValidationDataType.Currency:
  329. return ConvertCurrency (text, type, ref convertedValue);
  330. }
  331. } catch (Exception) {
  332. convertedValue = null;
  333. }
  334. return (convertedValue != null);
  335. }
  336. }
  337. }