Judgement.java 35 KB

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