Verifies.java 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953
  1. package cn.com.ty.lift.common.verify;
  2. import lombok.extern.slf4j.Slf4j;
  3. import java.lang.reflect.Array;
  4. import java.math.BigDecimal;
  5. import java.math.BigInteger;
  6. import java.net.IDN;
  7. import java.time.*;
  8. import java.time.chrono.HijrahDate;
  9. import java.time.chrono.JapaneseDate;
  10. import java.time.chrono.MinguoDate;
  11. import java.time.chrono.ThaiBuddhistDate;
  12. import java.time.temporal.TemporalAccessor;
  13. import java.util.*;
  14. import java.util.regex.Matcher;
  15. import java.util.regex.PatternSyntaxException;
  16. import static java.util.regex.Pattern.CASE_INSENSITIVE;
  17. /**
  18. * the validation for parameter implements javax.validation.constraints.*,
  19. * reform from hibernate validator (v6.0.16.Final)
  20. *
  21. * @author wcz
  22. * @since 2020/2/15
  23. */
  24. @Slf4j
  25. public class Verifies {
  26. private static final int MAX_LOCAL_PART_LENGTH = 64;
  27. private static final String LOCAL_PART_ATOM = "[a-z0-9!#$%&'*+/=?^_`{|}~\u0080-\uFFFF-]";
  28. private static final String LOCAL_PART_INSIDE_QUOTES_ATOM = "([a-z0-9!#$%&'*.(),<>\\[\\]:; @+/=?^_`{|}~\u0080-\uFFFF-]|\\\\\\\\|\\\\\\\")";
  29. /**
  30. * Regular expression for the local part of an email address (everything before '@')
  31. */
  32. private static final java.util.regex.Pattern LOCAL_PART_PATTERN = java.util.regex.Pattern.compile(
  33. "(" + LOCAL_PART_ATOM + "+|\"" + LOCAL_PART_INSIDE_QUOTES_ATOM + "+\")" +
  34. "(\\." + "(" + LOCAL_PART_ATOM + "+|\"" + LOCAL_PART_INSIDE_QUOTES_ATOM + "+\")" + ")*", CASE_INSENSITIVE
  35. );
  36. /**
  37. * This is the maximum length of a domain name. But be aware that each label (parts separated by a dot) of the
  38. * domain name must be at most 63 characters long. This is verified by {@link IDN#toASCII(String)}.
  39. */
  40. private static final int MAX_DOMAIN_PART_LENGTH = 255;
  41. private static final String DOMAIN_CHARS_WITHOUT_DASH = "[a-z\u0080-\uFFFF0-9!#$%&'*+/=?^_`{|}~]";
  42. private static final String DOMAIN_LABEL = "(" + DOMAIN_CHARS_WITHOUT_DASH + "-*)*" + DOMAIN_CHARS_WITHOUT_DASH + "+";
  43. private static final String DOMAIN = DOMAIN_LABEL + "+(\\." + DOMAIN_LABEL + "+)*";
  44. private static final String IP_DOMAIN = "[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}";
  45. //IP v6 regex taken from http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
  46. private static final String IP_V6_DOMAIN = "(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))";
  47. /**
  48. * Regular expression for the domain part of an URL
  49. * <p>
  50. * A host string must be a domain string, an IPv4 address string, or "[", followed by an IPv6 address string,
  51. * followed by "]".
  52. */
  53. private static final java.util.regex.Pattern DOMAIN_PATTERN = java.util.regex.Pattern.compile(
  54. DOMAIN + "|\\[" + IP_V6_DOMAIN + "\\]", CASE_INSENSITIVE
  55. );
  56. /**
  57. * Regular expression for the domain part of an email address (everything after '@')
  58. */
  59. private static final java.util.regex.Pattern EMAIL_DOMAIN_PATTERN = java.util.regex.Pattern.compile(
  60. DOMAIN + "|\\[" + IP_DOMAIN + "\\]|" + "\\[IPv6:" + IP_V6_DOMAIN + "\\]", CASE_INSENSITIVE
  61. );
  62. private static final OptionalInt LESS_THAN = OptionalInt.of(-1);
  63. private static final OptionalInt FINITE_VALUE = OptionalInt.empty();
  64. private static final OptionalInt GREATER_THAN = OptionalInt.of(1);
  65. private static final short SHORT_ZERO = (short) 0;
  66. private static final byte BYTE_ZERO = (byte) 0;
  67. private static final Clock SYSTEM_DEFAULT_CLOCK = Clock.offset(Clock.systemDefaultZone(), Duration.ZERO.abs().negated());
  68. private Verifies(){}
  69. public static boolean isNull(Object value) {
  70. return null == value;
  71. }
  72. public static boolean notNull(Object value) {
  73. return null != value;
  74. }
  75. private static class VerifyUtils{
  76. private static VerifyException exception(String message){
  77. return new VerifyException(message);
  78. }
  79. private static void isTrue(boolean expression, String message) {
  80. if (expression) {
  81. throw exception(message);
  82. }
  83. }
  84. private static void notTrue(boolean expression, String message) {
  85. if (!expression) {
  86. throw exception(message);
  87. }
  88. }
  89. private static void isNull(Object value, String message) {
  90. isTrue(null == value, message);
  91. }
  92. }
  93. private static class IllegalArg{
  94. private static IllegalArgumentException exception(String message) {
  95. return new IllegalArgumentException(message);
  96. }
  97. private static void isTrue(boolean expression, String message) {
  98. if (expression) {
  99. throw exception(message);
  100. }
  101. }
  102. private static void isNull(Object value, String message) {
  103. isTrue(null == value, message);
  104. }
  105. }
  106. public static boolean gt0(int value) {
  107. return value > 0;
  108. }
  109. public static boolean lt0(int value) {
  110. return value < 0;
  111. }
  112. public static boolean gte0(int value) {
  113. return value >= 0;
  114. }
  115. public static boolean lte0(int value) {
  116. return value <= 0;
  117. }
  118. public static boolean isCharSequence(Object value) {
  119. return (value instanceof CharSequence);
  120. }
  121. public static boolean isBigDecimal(Object value) {
  122. return (value instanceof BigDecimal);
  123. }
  124. public static boolean isBigInteger(Object value) {
  125. return (value instanceof BigInteger);
  126. }
  127. public static boolean isLong(Object value) {
  128. return (value instanceof Long);
  129. }
  130. public static boolean isInteger(Object value) {
  131. return (value instanceof Integer);
  132. }
  133. public static boolean isDouble(Object value) {
  134. return (value instanceof Double);
  135. }
  136. public static boolean isFloat(Object value) {
  137. return (value instanceof Float);
  138. }
  139. public static boolean isByte(Object value) {
  140. return (value instanceof Byte);
  141. }
  142. public static boolean isShort(Object value) {
  143. return (value instanceof Short);
  144. }
  145. public static boolean isString(Object value) {
  146. return (value instanceof String);
  147. }
  148. public static boolean isCollection(Object value) {
  149. return (value instanceof Collection);
  150. }
  151. public static boolean isMap(Object value) {
  152. return (value instanceof Map);
  153. }
  154. public static boolean isArray(Object value) {
  155. return value.getClass().isArray();
  156. }
  157. public static boolean isIterator(Object value) {
  158. return (value instanceof Iterator);
  159. }
  160. public static boolean isEnumeration(Object value) {
  161. return (value instanceof Enumeration);
  162. }
  163. private static BigDecimal newBigDecimal(CharSequence value) {
  164. try {
  165. BigDecimal bd;
  166. if (isString(value)) {
  167. bd = new BigDecimal((String) value);
  168. } else {
  169. bd = new BigDecimal(value.toString());
  170. }
  171. return bd;
  172. } catch (Exception e) {
  173. return null;
  174. }
  175. }
  176. private static BigDecimal newBigDecimal(Number value) {
  177. try {
  178. BigDecimal bd;
  179. if (isLong(value)) {
  180. bd = BigDecimal.valueOf((Long) value);
  181. } else if (isBigDecimal(value)) {
  182. bd = ((BigDecimal) value);
  183. } else if (isBigInteger(value)) {
  184. bd = new BigDecimal((BigInteger) value);
  185. } else if (isDouble(value)) {
  186. bd = BigDecimal.valueOf((Double) value);
  187. } else if (isFloat(value)) {
  188. bd = BigDecimal.valueOf((Float) value);
  189. } else {
  190. bd = BigDecimal.valueOf(value.doubleValue());
  191. }
  192. return bd;
  193. } catch (Exception e) {
  194. return null;
  195. }
  196. }
  197. private static OptionalInt infinityCheck(Double number, OptionalInt treatNanAs) {
  198. OptionalInt result = FINITE_VALUE;
  199. if (number == Double.NEGATIVE_INFINITY) {
  200. result = LESS_THAN;
  201. } else if (number.isNaN()) {
  202. result = treatNanAs;
  203. } else if (number == Double.POSITIVE_INFINITY) {
  204. result = GREATER_THAN;
  205. }
  206. return result;
  207. }
  208. private static OptionalInt infinityCheck(Float number, OptionalInt treatNanAs) {
  209. OptionalInt result = FINITE_VALUE;
  210. if (number == Float.NEGATIVE_INFINITY) {
  211. result = LESS_THAN;
  212. } else if (number.isNaN()) {
  213. result = treatNanAs;
  214. } else if (number == Float.POSITIVE_INFINITY) {
  215. result = GREATER_THAN;
  216. }
  217. return result;
  218. }
  219. /**
  220. * Checks the validity of the domain name used in an email. To be valid it should be either a valid host name, or an
  221. * IP address wrapped in [].
  222. *
  223. * @param domain domain to check for validity
  224. * @return {@code true} if the provided string is a valid domain, {@code false} otherwise
  225. */
  226. public static boolean isValidEmailDomainAddress(String domain) {
  227. return isValidDomainAddress(domain, EMAIL_DOMAIN_PATTERN);
  228. }
  229. /**
  230. * Checks validity of a domain name.
  231. *
  232. * @param domain the domain to check for validity
  233. * @return {@code true} if the provided string is a valid domain, {@code false} otherwise
  234. */
  235. public static boolean isValidDomainAddress(String domain) {
  236. return isValidDomainAddress(domain, DOMAIN_PATTERN);
  237. }
  238. private static boolean isValidDomainAddress(String domain, java.util.regex.Pattern pattern) {
  239. // if we have a trailing dot the domain part we have an invalid email address.
  240. // the regular expression match would take care of this, but IDN.toASCII drops the trailing '.'
  241. if (domain.endsWith(".")) {
  242. return false;
  243. }
  244. Matcher matcher = pattern.matcher(domain);
  245. if (!matcher.matches()) {
  246. return false;
  247. }
  248. String asciiString;
  249. try {
  250. asciiString = IDN.toASCII(domain);
  251. } catch (IllegalArgumentException e) {
  252. return false;
  253. }
  254. if (asciiString.length() > MAX_DOMAIN_PART_LENGTH) {
  255. return false;
  256. }
  257. return true;
  258. }
  259. //NotNull : Object
  260. public static void notNull(Object value, String message) {
  261. VerifyUtils.isTrue(isNull(value), message);
  262. }
  263. //Null : Object
  264. public static void isNull(Object value, String message) {
  265. VerifyUtils.isTrue(notNull(value), message);
  266. }
  267. //AssertTrue : Boolean
  268. public static void assertTrue(Boolean value, String message) {
  269. VerifyUtils.isNull(value, message);
  270. VerifyUtils.isTrue(!value, message);
  271. }
  272. //AssertFalse : Boolean
  273. public static void assertFalse(Boolean value, String message) {
  274. VerifyUtils.isNull(value, message);
  275. VerifyUtils.isTrue(value, message);
  276. }
  277. //decimalMax : number
  278. public static void decimalMax(Number value, BigDecimal maxValue, boolean inclusive, String message) {
  279. VerifyUtils.isNull(value, message);
  280. IllegalArg.isNull(maxValue, maxValue + " does not represent a valid BigDecimal format.");
  281. BigDecimal val = newBigDecimal(value);
  282. VerifyUtils.isNull(val, message);
  283. int compare = decimalComparator(value, val, maxValue, GREATER_THAN);
  284. //inclusive ? comparisonResult <= 0 : comparisonResult < 0;
  285. if (inclusive) {
  286. VerifyUtils.notTrue(lte0(compare), message);
  287. } else {
  288. VerifyUtils.notTrue(lt0(compare), message);
  289. }
  290. }
  291. public static void decimalMax(Number value, BigDecimal maxValue, String message) {
  292. decimalMax(value, maxValue, true, message);
  293. }
  294. //decimalMax : CharSequence
  295. public static void decimalMax(CharSequence value, BigDecimal maxValue, boolean inclusive, String message) {
  296. VerifyUtils.isNull(value, message);
  297. IllegalArg.isNull(maxValue, maxValue + " does not represent a valid BigDecimal format.");
  298. BigDecimal val = newBigDecimal(value.toString().trim());
  299. VerifyUtils.isNull(val, message);
  300. int compare = decimalComparator(value, val, maxValue, GREATER_THAN);
  301. //inclusive ? comparisonResult <= 0 : comparisonResult < 0;
  302. if (inclusive) {
  303. VerifyUtils.notTrue(lte0(compare), message);
  304. } else {
  305. VerifyUtils.notTrue(lt0(compare), message);
  306. }
  307. }
  308. public static void decimalMax(CharSequence value, BigDecimal maxValue, String message) {
  309. decimalMax(value, maxValue, true, message);
  310. }
  311. //decimalMin : number
  312. public static void decimalMin(Number value, BigDecimal minValue, boolean inclusive, String message) {
  313. VerifyUtils.isNull(value, message);
  314. IllegalArg.isNull(minValue, minValue + " does not represent a valid BigDecimal format.");
  315. BigDecimal val = newBigDecimal(value);
  316. VerifyUtils.isNull(val, message);
  317. int compare = decimalComparator(value, val, minValue, LESS_THAN);
  318. //inclusive ? comparisonResult >= 0 : comparisonResult > 0;
  319. if (inclusive) {
  320. VerifyUtils.notTrue(gte0(compare), message);
  321. } else {
  322. VerifyUtils.notTrue(gt0(compare), message);
  323. }
  324. }
  325. public static void decimalMin(Number value, BigDecimal minValue, String message) {
  326. decimalMin(value, minValue, true, message);
  327. }
  328. //decimalMin : CharSequence
  329. public static void decimalMin(CharSequence value, BigDecimal minValue, boolean inclusive, String message) {
  330. VerifyUtils.isNull(value, message);
  331. IllegalArg.isNull(minValue, minValue + " does not represent a valid BigDecimal format.");
  332. BigDecimal val = newBigDecimal(value.toString().trim());
  333. VerifyUtils.isNull(val, message);
  334. int compare = decimalComparator(value, val, minValue, LESS_THAN);
  335. //inclusive ? comparisonResult >= 0 : comparisonResult > 0;
  336. if (inclusive) {
  337. VerifyUtils.notTrue(gte0(compare), message);
  338. } else {
  339. VerifyUtils.notTrue(gt0(compare), message);
  340. }
  341. }
  342. public static void decimalMin(CharSequence value, BigDecimal minValue, String message) {
  343. decimalMin(value, minValue, true, message);
  344. }
  345. private static int decimalComparator(Object value, BigDecimal val, BigDecimal boundary, OptionalInt treatNanAs) {
  346. int compare;
  347. if (isLong(value) || isBigInteger(value) || isBigDecimal(value)) {
  348. compare = val.compareTo(boundary);
  349. } else if (isDouble(value)) {
  350. Double v = (Double) value;
  351. OptionalInt infinity = infinityCheck(v, treatNanAs);
  352. if (infinity.isPresent()) {
  353. compare = infinity.getAsInt();
  354. } else {
  355. compare = val.compareTo(boundary);
  356. }
  357. } else if (isFloat(value)) {
  358. Float v = (Float) value;
  359. OptionalInt infinity = infinityCheck(v, treatNanAs);
  360. if (infinity.isPresent()) {
  361. compare = infinity.getAsInt();
  362. } else {
  363. compare = val.compareTo(boundary);
  364. }
  365. } else {
  366. compare = val.compareTo(boundary);
  367. }
  368. return compare;
  369. }
  370. //length : CharSequence,Collection,Map,Array,Iterator,Enumeration
  371. public static int length(Object value) {
  372. if (isNull(value)) {
  373. return 0;
  374. }
  375. if (isCharSequence(value)) {
  376. return ((CharSequence) value).length();
  377. }
  378. if (isCollection(value)) {
  379. return ((Collection<?>) value).size();
  380. }
  381. if (isMap(value)) {
  382. return ((Map<?, ?>) value).size();
  383. }
  384. if (isArray(value)) {
  385. return Array.getLength(value);
  386. }
  387. int count;
  388. if (isIterator(value)) {
  389. Iterator<?> iter = (Iterator<?>) value;
  390. count = 0;
  391. while (iter.hasNext()) {
  392. count++;
  393. iter.next();
  394. }
  395. return count;
  396. }
  397. if (isEnumeration(value)) {
  398. Enumeration<?> enumeration = (Enumeration<?>) value;
  399. count = 0;
  400. while (enumeration.hasMoreElements()) {
  401. count++;
  402. enumeration.nextElement();
  403. }
  404. return count;
  405. }
  406. return -1;
  407. }
  408. //NotEmpty : CharSequence,Collection,Map,Array,Iterator,Enumeration
  409. public static void notEmpty(CharSequence value, String message) {
  410. VerifyUtils.isNull(value, message);
  411. VerifyUtils.notTrue(gt0(value.length()), message);
  412. }
  413. public static void notEmpty(Collection<?> value, String message) {
  414. VerifyUtils.isNull(value, message);
  415. VerifyUtils.isTrue(value.isEmpty(), message);
  416. }
  417. public static void notEmpty(Map<?, ?> value, String message) {
  418. VerifyUtils.isNull(value, message);
  419. VerifyUtils.isTrue(value.isEmpty(), message);
  420. }
  421. public static void notEmpty(Iterator<?> value, String message) {
  422. VerifyUtils.isNull(value, message);
  423. VerifyUtils.notTrue(value.hasNext(), message);
  424. }
  425. public static void notEmpty(Enumeration<?> value, String message) {
  426. VerifyUtils.isNull(value, message);
  427. VerifyUtils.notTrue(value.hasMoreElements(), message);
  428. }
  429. public static <T> void notEmpty(T[] value, String message) {
  430. VerifyUtils.isNull(value, message);
  431. VerifyUtils.notTrue(gt0(value.length), message);
  432. }
  433. public static void between(int value, int min, int max, String message) {
  434. IllegalArg.isTrue(lt0(min), "The min parameter cannot be negative.");
  435. IllegalArg.isTrue(lt0(max), "The max parameter cannot be negative.");
  436. IllegalArg.isTrue(min > max, "The min and max length cannot be negative.");
  437. //value >= min && value <= max
  438. VerifyUtils.notTrue(value >= min && value <= max, message);
  439. }
  440. //Size : CharSequence,Collection,Map,Array,Iterator,Enumeration
  441. public static void size(Object value, int min, int max, String message) {
  442. VerifyUtils.isNull(value, message);
  443. between(length(value), min, max, message);
  444. }
  445. public static void size(Object value, String message) {
  446. VerifyUtils.isNull(value, message);
  447. between(length(value), 0, Integer.MAX_VALUE, message);
  448. }
  449. //Size : CharSequence,Collection,Map,Array,Iterator,Enumeration
  450. public static void upper(Object value, int min, String message) {
  451. VerifyUtils.isNull(value, message);
  452. between(length(value), min, Integer.MAX_VALUE, message);
  453. }
  454. //Size : CharSequence,Collection,Map,Array,Iterator,Enumeration
  455. public static void lower(Object value, int max, String message) {
  456. VerifyUtils.isNull(value, message);
  457. between(length(value), 0, max, message);
  458. }
  459. public static void digits(BigDecimal value, int maxInteger, int maxFraction, String message) {
  460. IllegalArg.isTrue(lt0(maxInteger), "The length of the integer part cannot be negative.");
  461. IllegalArg.isTrue(lt0(maxFraction), "The length of the fraction part cannot be negative.");
  462. int integerPart = value.precision() - value.scale();
  463. int fractionPart = value.scale() < 0 ? 0 : value.scale();
  464. //maxInteger >= integerPart && maxFraction >= fractionPart
  465. VerifyUtils.notTrue(maxInteger >= integerPart && maxFraction >= fractionPart, message);
  466. }
  467. //Digits : CharSequence,Number
  468. public static void digits(CharSequence value, int maxInteger, int maxFraction, String message) {
  469. VerifyUtils.isNull(value, message);
  470. BigDecimal val = newBigDecimal(value);
  471. VerifyUtils.isNull(val, value + " does not represent a valid BigDecimal format.");
  472. digits(val, maxInteger, maxFraction, message);
  473. }
  474. //Digits : CharSequence,Number
  475. public static void digits(Number value, int maxInteger, int maxFraction, String message) {
  476. VerifyUtils.isNull(value, message);
  477. BigDecimal val;
  478. if (isBigDecimal(value)) {
  479. val = (BigDecimal) value;
  480. } else {
  481. val = new BigDecimal(value.toString());
  482. }
  483. VerifyUtils.isNull(val, value + " does not represent a valid BigDecimal format.");
  484. val = val.stripTrailingZeros();
  485. digits(val, maxInteger, maxFraction, message);
  486. }
  487. //NotBlank : CharSequence
  488. public static void notBlank(CharSequence value, String message) {
  489. VerifyUtils.isNull(value, message);
  490. VerifyUtils.notTrue(value.toString().trim().isEmpty(), message);
  491. }
  492. //Email : CharSequence
  493. public static void email(CharSequence value, String regexp, Flag[] flags, String message) {
  494. VerifyUtils.isNull(value, message);
  495. String val = value.toString().trim();
  496. // cannot split email string at @ as it can be a part of quoted local part of email.
  497. // so we need to split at a position of last @ present in the string:
  498. int splitPosition = val.lastIndexOf('@');
  499. // need to check if
  500. VerifyUtils.isTrue(lt0(splitPosition), message);
  501. String localPart = val.substring(0, splitPosition);
  502. String domainPart = val.substring(splitPosition + 1);
  503. VerifyUtils.isTrue(localPart.length() > MAX_LOCAL_PART_LENGTH, message);
  504. VerifyUtils.notTrue(LOCAL_PART_PATTERN.matcher(localPart).matches(), message);
  505. VerifyUtils.notTrue(isValidEmailDomainAddress(domainPart), message);
  506. //valid by the pattern
  507. pattern(value, ".*", message);
  508. }
  509. public static void email(CharSequence value, String message) {
  510. Flag[] flags = {};
  511. email(value, ".*", flags, message);
  512. }
  513. public static void pattern(CharSequence value, String regexp, Flag[] flags, String message) {
  514. VerifyUtils.isNull(value, message);
  515. IllegalArg.isNull(regexp, "The regexp is Invalid regular expression.");
  516. int intFlag = 0;
  517. for (Flag flag : flags) {
  518. intFlag = intFlag | flag.getValue();
  519. }
  520. java.util.regex.Pattern pattern = null;
  521. // we only apply the regexp if there is one to apply
  522. if (!".*".equals(regexp) || flags.length > 0) {
  523. try {
  524. pattern = java.util.regex.Pattern.compile(regexp, intFlag);
  525. } catch (PatternSyntaxException e) {
  526. throw VerifyUtils.exception("The regexp is Invalid regular expression.");
  527. }
  528. }
  529. IllegalArg.isNull(pattern, "The regexp is Invalid regular expression.");
  530. VerifyUtils.notTrue(pattern.matcher(value.toString()).matches(), message);
  531. }
  532. public static void pattern(CharSequence value, String regexp, String message) {
  533. Flag[] flags = {};
  534. pattern(value, regexp, flags, message);
  535. }
  536. /**
  537. * Possible Regexp flags.
  538. */
  539. public enum Flag {
  540. /**
  541. * Enables Unix lines mode.
  542. *
  543. * @see java.util.regex.Pattern#UNIX_LINES
  544. */
  545. UNIX_LINES(java.util.regex.Pattern.UNIX_LINES),
  546. /**
  547. * Enables case-insensitive matching.
  548. *
  549. * @see java.util.regex.Pattern#CASE_INSENSITIVE
  550. */
  551. CASE_INSENSITIVE(java.util.regex.Pattern.CASE_INSENSITIVE),
  552. /**
  553. * Permits whitespace and comments in pattern.
  554. *
  555. * @see java.util.regex.Pattern#COMMENTS
  556. */
  557. COMMENTS(java.util.regex.Pattern.COMMENTS),
  558. /**
  559. * Enables multiline mode.
  560. *
  561. * @see java.util.regex.Pattern#MULTILINE
  562. */
  563. MULTILINE(java.util.regex.Pattern.MULTILINE),
  564. /**
  565. * Enables dotall mode.
  566. *
  567. * @see java.util.regex.Pattern#DOTALL
  568. */
  569. DOTALL(java.util.regex.Pattern.DOTALL),
  570. /**
  571. * Enables Unicode-aware case folding.
  572. *
  573. * @see java.util.regex.Pattern#UNICODE_CASE
  574. */
  575. UNICODE_CASE(java.util.regex.Pattern.UNICODE_CASE),
  576. /**
  577. * Enables canonical equivalence.
  578. *
  579. * @see java.util.regex.Pattern#CANON_EQ
  580. */
  581. CANON_EQ(java.util.regex.Pattern.CANON_EQ);
  582. //JDK flag value
  583. private final int value;
  584. Flag(int value) {
  585. this.value = value;
  586. }
  587. /**
  588. * @return flag value as defined in {@link java.util.regex.Pattern}
  589. */
  590. public int getValue() {
  591. return value;
  592. }
  593. }
  594. //Max : CharSequence
  595. public static void max(CharSequence value, long max, String message) {
  596. VerifyUtils.isNull(value, message);
  597. String v = value.toString().trim();
  598. VerifyUtils.isTrue(v.isEmpty(), message);
  599. BigDecimal val = newBigDecimal(v);
  600. VerifyUtils.isNull(val, message);
  601. int compare = val.compareTo(BigDecimal.valueOf(max));
  602. VerifyUtils.notTrue(lte0(compare), message);
  603. }
  604. //Max : Number
  605. public static void max(Number value, long max, String message) {
  606. VerifyUtils.isNull(value, message);
  607. int compare = numberComparator(value, max, GREATER_THAN);
  608. VerifyUtils.notTrue(lte0(compare), message);
  609. }
  610. //min : CharSequence
  611. public static void min(CharSequence value, long min, String message) {
  612. VerifyUtils.isNull(value, message);
  613. String v = value.toString().trim();
  614. VerifyUtils.isTrue(v.isEmpty(), message);
  615. BigDecimal val = newBigDecimal(v);
  616. VerifyUtils.isNull(val, message);
  617. int compare = val.compareTo(BigDecimal.valueOf(min));
  618. VerifyUtils.notTrue(gte0(compare), message);
  619. }
  620. //min : Number
  621. public static void min(Number value, long min, String message) {
  622. VerifyUtils.isNull(value, message);
  623. int compare = numberComparator(value, min, LESS_THAN);
  624. VerifyUtils.notTrue(gte0(compare), message);
  625. }
  626. //
  627. private static int numberComparator(Number value, long boundary, OptionalInt treatNanAs) {
  628. int compare;
  629. if (isLong(value)) {
  630. compare = ((Long) value).compareTo(boundary);
  631. } else if (isDouble(value)) {
  632. Double val = (Double) value;
  633. OptionalInt infinity = infinityCheck(val, treatNanAs);
  634. if (infinity.isPresent()) {
  635. compare = infinity.getAsInt();
  636. } else {
  637. compare = Double.compare(val, boundary);
  638. }
  639. } else if (isFloat(value)) {
  640. Float val = (Float) value;
  641. OptionalInt infinity = infinityCheck(val, treatNanAs);
  642. if (infinity.isPresent()) {
  643. compare = infinity.getAsInt();
  644. } else {
  645. compare = Float.compare(val, boundary);
  646. }
  647. } else if (isBigDecimal(value)) {
  648. compare = ((BigDecimal) value).compareTo(BigDecimal.valueOf(boundary));
  649. } else if (isBigInteger(value)) {
  650. compare = ((BigInteger) value).compareTo(BigInteger.valueOf(boundary));
  651. } else {
  652. compare = Long.compare(value.longValue(), boundary);
  653. }
  654. return compare;
  655. }
  656. private static int signum(Number value, OptionalInt treatNanAs) {
  657. int signum;
  658. if (isLong(value)) {
  659. signum = Long.signum((Long) value);
  660. } else if (isInteger(value)) {
  661. signum = Integer.signum((Integer) value);
  662. } else if (isBigDecimal(value)) {
  663. signum = ((BigDecimal) value).signum();
  664. } else if (isBigInteger(value)) {
  665. signum = ((BigInteger) value).signum();
  666. } else if (isDouble(value)) {
  667. Double val = (Double) value;
  668. OptionalInt infinity = infinityCheck(val, treatNanAs);
  669. if (infinity.isPresent()) {
  670. signum = infinity.getAsInt();
  671. } else {
  672. signum = val.compareTo(0D);
  673. }
  674. } else if (isFloat(value)) {
  675. Float val = (Float) value;
  676. OptionalInt infinity = infinityCheck(val, treatNanAs);
  677. if (infinity.isPresent()) {
  678. signum = infinity.getAsInt();
  679. } else {
  680. signum = val.compareTo(0F);
  681. }
  682. } else if (isByte(value)) {
  683. signum = ((Byte) value).compareTo(BYTE_ZERO);
  684. } else if (isShort(value)) {
  685. signum = ((Short) value).compareTo(SHORT_ZERO);
  686. } else {
  687. signum = Double.compare(value.doubleValue(), 0D);
  688. }
  689. return signum;
  690. }
  691. //Negative : Number
  692. public static void negative(Number value, String message) {
  693. VerifyUtils.isNull(value, message);
  694. VerifyUtils.notTrue(lt0(signum(value, GREATER_THAN)), message);
  695. }
  696. // NegativeOrZero : Number
  697. public static void negativeOrZero(Number value, String message) {
  698. VerifyUtils.isNull(value, message);
  699. VerifyUtils.notTrue(lte0(signum(value, GREATER_THAN)), message);
  700. }
  701. //Positive : Number
  702. public static void positive(Number value, String message) {
  703. VerifyUtils.isNull(value, message);
  704. VerifyUtils.notTrue(gt0(signum(value, LESS_THAN)), message);
  705. }
  706. //PositiveOrZero : Number
  707. public static void positiveOrZero(Number value, String message) {
  708. VerifyUtils.isNull(value, message);
  709. VerifyUtils.notTrue(gte0(signum(value, LESS_THAN)), message);
  710. }
  711. //java.time.temporal.TemporalAccessor
  712. public static int dateComparator(TemporalAccessor value) {
  713. int compare;
  714. if (value instanceof Instant) {
  715. compare = ((Instant) value).compareTo(Instant.now(SYSTEM_DEFAULT_CLOCK));
  716. } else if (value instanceof LocalDateTime) {
  717. compare = ((LocalDateTime) value).compareTo(LocalDateTime.now(SYSTEM_DEFAULT_CLOCK));
  718. } else if (value instanceof LocalDate) {
  719. compare = ((LocalDate) value).compareTo(LocalDate.now(SYSTEM_DEFAULT_CLOCK));
  720. } else if (value instanceof LocalTime) {
  721. compare = ((LocalTime) value).compareTo(LocalTime.now(SYSTEM_DEFAULT_CLOCK));
  722. } else if (value instanceof MonthDay) {
  723. compare = ((MonthDay) value).compareTo(MonthDay.now(SYSTEM_DEFAULT_CLOCK));
  724. } else if (value instanceof HijrahDate) {
  725. compare = ((HijrahDate) value).compareTo(HijrahDate.now(SYSTEM_DEFAULT_CLOCK));
  726. } else if (value instanceof JapaneseDate) {
  727. compare = ((JapaneseDate) value).compareTo(JapaneseDate.now(SYSTEM_DEFAULT_CLOCK));
  728. } else if (value instanceof MinguoDate) {
  729. compare = ((MinguoDate) value).compareTo(MinguoDate.now(SYSTEM_DEFAULT_CLOCK));
  730. } else if (value instanceof OffsetDateTime) {
  731. compare = ((OffsetDateTime) value).compareTo(OffsetDateTime.now(SYSTEM_DEFAULT_CLOCK));
  732. } else if (value instanceof OffsetTime) {
  733. compare = ((OffsetTime) value).compareTo(OffsetTime.now(SYSTEM_DEFAULT_CLOCK));
  734. } else if (value instanceof ThaiBuddhistDate) {
  735. compare = ((ThaiBuddhistDate) value).compareTo(ThaiBuddhistDate.now(SYSTEM_DEFAULT_CLOCK));
  736. } else if (value instanceof Year) {
  737. compare = ((Year) value).compareTo(Year.now(SYSTEM_DEFAULT_CLOCK));
  738. } else if (value instanceof YearMonth) {
  739. compare = ((YearMonth) value).compareTo(YearMonth.now(SYSTEM_DEFAULT_CLOCK));
  740. } else if (value instanceof ZonedDateTime) {
  741. compare = ((ZonedDateTime) value).compareTo(ZonedDateTime.now(SYSTEM_DEFAULT_CLOCK));
  742. } else {
  743. compare = Integer.MAX_VALUE;
  744. }
  745. return compare;
  746. }
  747. //Future : java.time.temporal.TemporalAccessor
  748. public static void future(TemporalAccessor value, String message) {
  749. VerifyUtils.isNull(value, message);
  750. int compare = dateComparator(value);
  751. IllegalArg.isTrue(Integer.MAX_VALUE == compare, value.getClass().toString() + " is not a supported TemporalAccessor class temporarily.");
  752. VerifyUtils.notTrue(gt0(compare), message);
  753. }
  754. //Future : java.util.Date,
  755. public static void future(Date value, String message) {
  756. VerifyUtils.isNull(value, message);
  757. int compare = value.toInstant().compareTo(Instant.now(SYSTEM_DEFAULT_CLOCK));
  758. VerifyUtils.notTrue(gt0(compare), message);
  759. }
  760. //Future : java.util.Calendar
  761. public static void future(Calendar value, String message) {
  762. VerifyUtils.isNull(value, message);
  763. int compare = value.toInstant().compareTo(Instant.now(SYSTEM_DEFAULT_CLOCK));
  764. VerifyUtils.notTrue(gte0(compare), message);
  765. }
  766. //FutureOrPresent : java.time.temporal.TemporalAccessor
  767. public static void futureOrPresent(TemporalAccessor value, String message) {
  768. VerifyUtils.isNull(value, message);
  769. int compare = dateComparator(value);
  770. IllegalArg.isTrue(Integer.MAX_VALUE == compare, value.getClass().toString() + " is not a supported TemporalAccessor class temporarily.");
  771. VerifyUtils.notTrue(gte0(compare), message);
  772. }
  773. //FutureOrPresent : java.util.Date,
  774. public static void futureOrPresent(Date value, String message) {
  775. VerifyUtils.isNull(value, message);
  776. int compare = value.toInstant().compareTo(Instant.now(SYSTEM_DEFAULT_CLOCK));
  777. VerifyUtils.notTrue(gt0(compare), message);
  778. }
  779. //FutureOrPresent : java.util.Calendar
  780. public static void futureOrPresent(Calendar value, String message) {
  781. VerifyUtils.isNull(value, message);
  782. int compare = value.toInstant().compareTo(Instant.now(SYSTEM_DEFAULT_CLOCK));
  783. VerifyUtils.notTrue(gte0(compare), message);
  784. }
  785. ///////////////
  786. //past : java.time.temporal.TemporalAccessor
  787. public static void past(TemporalAccessor value, String message) {
  788. VerifyUtils.isNull(value, message);
  789. int compare = dateComparator(value);
  790. IllegalArg.isNull(Integer.MAX_VALUE == compare, value.getClass().toString() + " is not a supported TemporalAccessor class temporarily.");
  791. VerifyUtils.notTrue(lt0(compare), message);
  792. }
  793. //past : java.util.Date,
  794. public static void past(Date value, String message) {
  795. VerifyUtils.isNull(value, message);
  796. int compare = value.toInstant().compareTo(Instant.now(SYSTEM_DEFAULT_CLOCK));
  797. VerifyUtils.notTrue(lt0(compare), message);
  798. }
  799. //past : java.util.Calendar
  800. public static void past(Calendar value, String message) {
  801. VerifyUtils.isNull(value, message);
  802. int compare = value.toInstant().compareTo(Instant.now(SYSTEM_DEFAULT_CLOCK));
  803. VerifyUtils.notTrue(lt0(compare), message);
  804. }
  805. //PastOrPresent : java.time.temporal.TemporalAccessor
  806. public static void pastOrPresent(TemporalAccessor value, String message) {
  807. VerifyUtils.isNull(value, message);
  808. int compare = dateComparator(value);
  809. IllegalArg.isTrue(Integer.MAX_VALUE == compare, value.getClass().toString() + " is not a supported TemporalAccessor class temporarily.");
  810. VerifyUtils.notTrue(lte0(compare), message);
  811. }
  812. //PastOrPresent : java.util.Date,
  813. public static void pastOrPresent(Date value, String message) {
  814. VerifyUtils.isNull(value, message);
  815. int compare = value.toInstant().compareTo(Instant.now(SYSTEM_DEFAULT_CLOCK));
  816. VerifyUtils.notTrue(lt0(compare), message);
  817. }
  818. //PastOrPresent : java.util.Calendar
  819. public static void pastOrPresent(Calendar value, String message) {
  820. VerifyUtils.isNull(value, message);
  821. int compare = value.toInstant().compareTo(Instant.now(SYSTEM_DEFAULT_CLOCK));
  822. VerifyUtils.notTrue(lte0(compare), message);
  823. }
  824. }