package cn.com.ty.lift.common.judge; import lombok.extern.slf4j.Slf4j; import javax.validation.constraints.*; import java.lang.reflect.Array; import java.math.BigDecimal; import java.math.BigInteger; import java.net.IDN; import java.time.*; import java.time.chrono.HijrahDate; import java.time.chrono.JapaneseDate; import java.time.chrono.MinguoDate; import java.time.chrono.ThaiBuddhistDate; import java.time.temporal.TemporalAccessor; import java.util.*; import java.util.regex.Matcher; import java.util.regex.PatternSyntaxException; import static java.util.regex.Pattern.CASE_INSENSITIVE; /** * the validation for parameter implements javax.validation.constraints.*, * reform from hibernate validator (v6.0.16.Final) * * @author wcz * @since 2020/2/15 */ public class Judgement { private ThreadLocal message = new ThreadLocal<>(); private ThreadLocal code = new ThreadLocal<>(); private static final int MAX_LOCAL_PART_LENGTH = 64; private static final String LOCAL_PART_ATOM = "[a-z0-9!#$%&'*+/=?^_`{|}~\u0080-\uFFFF-]"; private static final String LOCAL_PART_INSIDE_QUOTES_ATOM = "([a-z0-9!#$%&'*.(),<>\\[\\]:; @+/=?^_`{|}~\u0080-\uFFFF-]|\\\\\\\\|\\\\\\\")"; /** * Regular expression for the local part of an email address (everything before '@') */ private static final java.util.regex.Pattern LOCAL_PART_PATTERN = java.util.regex.Pattern.compile( "(" + LOCAL_PART_ATOM + "+|\"" + LOCAL_PART_INSIDE_QUOTES_ATOM + "+\")" + "(\\." + "(" + LOCAL_PART_ATOM + "+|\"" + LOCAL_PART_INSIDE_QUOTES_ATOM + "+\")" + ")*", CASE_INSENSITIVE ); /** * This is the maximum length of a domain name. But be aware that each label (parts separated by a dot) of the * domain name must be at most 63 characters long. This is verified by {@link IDN#toASCII(String)}. */ private static final int MAX_DOMAIN_PART_LENGTH = 255; private static final String DOMAIN_CHARS_WITHOUT_DASH = "[a-z\u0080-\uFFFF0-9!#$%&'*+/=?^_`{|}~]"; private static final String DOMAIN_LABEL = "(" + DOMAIN_CHARS_WITHOUT_DASH + "-*)*" + DOMAIN_CHARS_WITHOUT_DASH + "+"; private static final String DOMAIN = DOMAIN_LABEL + "+(\\." + DOMAIN_LABEL + "+)*"; private static final String IP_DOMAIN = "[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"; //IP v6 regex taken from http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses 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]))"; /** * Regular expression for the domain part of an URL *

* A host string must be a domain string, an IPv4 address string, or "[", followed by an IPv6 address string, * followed by "]". */ private static final java.util.regex.Pattern DOMAIN_PATTERN = java.util.regex.Pattern.compile( DOMAIN + "|\\[" + IP_V6_DOMAIN + "\\]", CASE_INSENSITIVE ); /** * Regular expression for the domain part of an email address (everything after '@') */ private static final java.util.regex.Pattern EMAIL_DOMAIN_PATTERN = java.util.regex.Pattern.compile( DOMAIN + "|\\[" + IP_DOMAIN + "\\]|" + "\\[IPv6:" + IP_V6_DOMAIN + "\\]", CASE_INSENSITIVE ); private static final OptionalInt LESS_THAN = OptionalInt.of(-1); private static final OptionalInt FINITE_VALUE = OptionalInt.empty(); private static final OptionalInt GREATER_THAN = OptionalInt.of(1); private static final short SHORT_ZERO = (short) 0; private static final byte BYTE_ZERO = (byte) 0; public String message() { String m = message.get(); message.remove(); return m; } public Integer code(){ Integer c = code.get(); code.remove(); return c; } private void setVerify(String message) { this.code.set(1); this.message.set(message); } private void setIllegalArg(String message){ this.code.set(2); this.message.set(message); } private Clock getClock() { return Clock.systemDefaultZone(); } private Duration getDuration() { return Duration.ZERO.abs(); } private Clock getClock(Duration offset) { return Clock.offset(getClock(), offset.negated()); } public boolean isNull(Object value) { return null == value; } public boolean notNull(Object value) { return null != value; } public boolean gt0(int value) { return value > 0; } public boolean lt0(int value) { return value < 0; } public boolean gte0(int value) { return value >= 0; } public boolean lte0(int value) { return value <= 0; } public boolean isBoolean(Object value) { return (value instanceof Boolean); } public boolean isNumber(Object value) { return (value instanceof Number); } public boolean isCharSequence(Object value) { return (value instanceof CharSequence); } public boolean isBigDecimal(Object value) { return (value instanceof BigDecimal); } public boolean isBigInteger(Object value) { return (value instanceof BigInteger); } public boolean isLong(Object value) { return (value instanceof Long); } public boolean isInteger(Object value) { return (value instanceof Integer); } public boolean isDouble(Object value) { return (value instanceof Double); } public boolean isFloat(Object value) { return (value instanceof Float); } public boolean isByte(Object value) { return (value instanceof Byte); } public boolean isShort(Object value) { return (value instanceof Short); } public boolean isString(Object value) { return (value instanceof String); } public boolean isCollection(Object value) { return (value instanceof Collection); } public boolean isMap(Object value) { return (value instanceof Map); } public boolean isArray(Object value) { return value.getClass().isArray(); } public boolean isIterator(Object value) { return (value instanceof Iterator); } public boolean isEnumeration(Object value) { return (value instanceof Enumeration); } public boolean isTemporalAccessor(Object value) { return (value instanceof TemporalAccessor); } public boolean isDate(Object value) { return (value instanceof Date); } public boolean isCalendar(Object value) { return (value instanceof Calendar); } private BigDecimal newBigDecimal(CharSequence value) { try { BigDecimal bd; if (isString(value)) { bd = new BigDecimal((String) value); } else { bd = new BigDecimal(value.toString()); } return bd; } catch (Exception e) { return null; } } private BigDecimal newBigDecimal(Number value) { try { BigDecimal bd; if (isLong(value)) { bd = BigDecimal.valueOf((Long) value); } else if (isBigDecimal(value)) { bd = ((BigDecimal) value); } else if (isBigInteger(value)) { bd = new BigDecimal((BigInteger) value); } else if (isDouble(value)) { bd = BigDecimal.valueOf((Double) value); } else if (isFloat(value)) { bd = BigDecimal.valueOf((Float) value); } else { bd = BigDecimal.valueOf(value.doubleValue()); } return bd; } catch (Exception e) { return null; } } public OptionalInt infinityCheck(Double number, OptionalInt treatNanAs) { OptionalInt result = FINITE_VALUE; if (number == Double.NEGATIVE_INFINITY) { result = LESS_THAN; } else if (number.isNaN()) { result = treatNanAs; } else if (number == Double.POSITIVE_INFINITY) { result = GREATER_THAN; } return result; } public OptionalInt infinityCheck(Float number, OptionalInt treatNanAs) { OptionalInt result = FINITE_VALUE; if (number == Float.NEGATIVE_INFINITY) { result = LESS_THAN; } else if (number.isNaN()) { result = treatNanAs; } else if (number == Float.POSITIVE_INFINITY) { result = GREATER_THAN; } return result; } /** * Checks the validity of the domain name used in an email. To be valid it should be either a valid host name, or an * IP address wrapped in []. * * @param domain domain to check for validity * @return {@code true} if the provided string is a valid domain, {@code false} otherwise */ public boolean isValidEmailDomainAddress(String domain) { return isValidDomainAddress(domain, EMAIL_DOMAIN_PATTERN); } /** * Checks validity of a domain name. * * @param domain the domain to check for validity * @return {@code true} if the provided string is a valid domain, {@code false} otherwise */ public boolean isValidDomainAddress(String domain) { return isValidDomainAddress(domain, DOMAIN_PATTERN); } private boolean isValidDomainAddress(String domain, java.util.regex.Pattern pattern) { // if we have a trailing dot the domain part we have an invalid email address. // the regular expression match would take care of this, but IDN.toASCII drops the trailing '.' if (domain.endsWith(".")) { return false; } Matcher matcher = pattern.matcher(domain); if (!matcher.matches()) { return false; } String asciiString; try { asciiString = IDN.toASCII(domain); } catch (IllegalArgumentException e) { return false; } if (asciiString.length() > MAX_DOMAIN_PART_LENGTH) { return false; } return true; } //NotNull : Object public boolean judge(Object value, NotNull annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); return notNull(value); } //Null : Object public boolean judge(Object value, Null annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); return isNull(value); } //AssertTrue : Boolean public boolean judge(Object value, AssertTrue annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); return notNull(value) && isBoolean(value) && ((Boolean) value); } //AssertFalse : Boolean public boolean judge(Object value, AssertFalse annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); return notNull(value) && isBoolean(value) && !((Boolean) value); } //DecimalMax : Number, CharSequence public boolean judge(Object value, DecimalMax annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } final boolean isNumber = isNumber(value); final boolean isCharSequence = isCharSequence(value); if (!isNumber && !isCharSequence) { setIllegalArg("The DecimalMax only for Number & CharSequence."); return false; } String maxValue = annotation.value(); if (isNull(maxValue)) { setIllegalArg("The value of DecimalMax is null, a invalid BigDecimal format."); return false; } BigDecimal max = newBigDecimal(maxValue); if (isNull(max)) { setIllegalArg(maxValue + " does not represent a valid BigDecimal format."); return false; } BigDecimal val; if (isNumber) { val = newBigDecimal((Number) value); } else { val = newBigDecimal((CharSequence) value); } if (isNull(val)) { setIllegalArg(value + " does not represent a valid BigDecimal format."); return false; } int compare = decimalComparator(value, val, max, GREATER_THAN); boolean inclusive = annotation.inclusive(); //inclusive ? comparisonResult <= 0 : comparisonResult < 0; if (inclusive) { return lte0(compare); } else { return lt0(compare); } } //DecimalMin : Number & CharSequence. public boolean judge(Object value, DecimalMin annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } final boolean isNumber = isNumber(value); final boolean isCharSequence = isCharSequence(value); if (!isNumber && !isCharSequence) { setIllegalArg("The DecimalMin only for Number & CharSequence."); return false; } String minValue = annotation.value(); if (isNull(minValue)) { setIllegalArg("The value of DecimalMin is null, a invalid BigDecimal format."); return false; } BigDecimal min = newBigDecimal(minValue); if (isNull(min)) { setIllegalArg(minValue + " does not represent a valid BigDecimal format."); return false; } BigDecimal val; if (isNumber) { val = newBigDecimal((Number) value); } else { val = newBigDecimal((CharSequence) value); } if (isNull(val)) { setIllegalArg(value + " does not represent a valid BigDecimal format."); return false; } int compare = decimalComparator(value, val, min, LESS_THAN); boolean inclusive = annotation.inclusive(); //inclusive ? comparisonResult >= 0 : comparisonResult > 0; if (inclusive) { return gte0(compare); } else { return gt0(compare); } } private int decimalComparator(Object value, BigDecimal val, BigDecimal min, OptionalInt treatNanAs) { int compare; if (isLong(value) || isBigInteger(value) || isBigDecimal(value)) { compare = val.compareTo(min); } else if (isDouble(value)) { Double v = (Double) value; OptionalInt infinity = infinityCheck(v, treatNanAs); if (infinity.isPresent()) { compare = infinity.getAsInt(); } else { compare = val.compareTo(min); } } else if (isFloat(value)) { Float v = (Float) value; OptionalInt infinity = infinityCheck(v, treatNanAs); if (infinity.isPresent()) { compare = infinity.getAsInt(); } else { compare = val.compareTo(min); } } else { compare = val.compareTo(min); } return compare; } //NotEmpty : CharSequence,Collection,Map,Array,Iterator,Enumeration public boolean judge(Object value, NotEmpty annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } int length = length(value); // length > 0 return gt0(length); } public int length(Object value) { if (isNull(value)) { return 0; } if (isCharSequence(value)) { return ((CharSequence) value).length(); } if (isCollection(value)) { return ((Collection) value).size(); } if (isMap(value)) { return ((Map) value).size(); } if (isArray(value)) { return Array.getLength(value); } int count; if (isIterator(value)) { Iterator iter = (Iterator) value; count = 0; while (iter.hasNext()) { count++; iter.next(); } return count; } if (isEnumeration(value)) { Enumeration enumeration = (Enumeration) value; count = 0; while (enumeration.hasMoreElements()) { count++; enumeration.nextElement(); } return count; } return -1; } //Size : CharSequence,Collection,Map,Array,Iterator,Enumeration public boolean judge(Object value, Size annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } int min = annotation.min(); int max = annotation.max(); if (lt0(min)) { setIllegalArg("The min parameter cannot be negative."); return false; } if (lt0(max)) { setIllegalArg("The max parameter cannot be negative."); return false; } if (min > max) { setIllegalArg("The min and max length cannot be negative."); return false; } int length = length(value); //size >= min && size <= max return length >= min && length <= max; } //Digits : CharSequence,Number public boolean judge(Object value, Digits annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } final boolean isNumber = isNumber(value); final boolean isCharSequence = isCharSequence(value); if (!isNumber && !isCharSequence) { setIllegalArg("The Digits only for Number & CharSequence."); return false; } int maxInteger = annotation.integer(); int maxFraction = annotation.fraction(); if (lt0(maxInteger)) { setIllegalArg("The length of the integer part cannot be negative."); return false; } if (lt0(maxFraction)) { setIllegalArg("The length of the fraction part cannot be negative."); return false; } BigDecimal val; if (isNumber) { if (isBigDecimal(value)) { val = (BigDecimal) value; } else { val = newBigDecimal(value.toString()); if (isNull(val)) { setIllegalArg(value + " does not represent a valid BigDecimal format."); return false; } val = val.stripTrailingZeros(); } } else { val = newBigDecimal((CharSequence) value); } if (isNull(val)) { setIllegalArg(value + " does not represent a valid BigDecimal format."); return false; } int integerPart = val.precision() - val.scale(); int fractionPart = val.scale() < 0 ? 0 : val.scale(); //maxInteger >= integerPart && maxFraction >= fractionPart return maxInteger >= integerPart && maxFraction >= fractionPart; } //NotBlank : CharSequence public boolean judge(Object value, NotBlank annotation) { if (isNull(annotation)) { return true; } setIllegalArg(annotation.message()); if (isNull(value)) { return false; } if (!isCharSequence(value)) { return true; } return ((CharSequence) value).toString().trim().isEmpty(); } //Email : CharSequence public boolean judge(Object value, Email annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value) || !isCharSequence(value)) { return false; } String val = ((CharSequence) value).toString().trim(); if (val.isEmpty()) { return false; } // cannot split email string at @ as it can be a part of quoted local part of email. // so we need to split at a position of last @ present in the string: int splitPosition = val.lastIndexOf('@'); // need to check if if (lt0(splitPosition)) { return false; } String localPart = val.substring(0, splitPosition); String domainPart = val.substring(splitPosition + 1); if (localPart.length() > MAX_LOCAL_PART_LENGTH) { return false; } if (!LOCAL_PART_PATTERN.matcher(localPart).matches()) { return false; } if (!isValidEmailDomainAddress(domainPart)) { return false; } Pattern.Flag[] flags = annotation.flags(); String regexp = annotation.regexp(); int intFlag = 0; for (Pattern.Flag flag : flags) { intFlag = intFlag | flag.getValue(); } java.util.regex.Pattern pattern = null; // we only apply the regexp if there is one to apply if (!".*".equals(regexp) || flags.length > 0) { try { pattern = java.util.regex.Pattern.compile(regexp, intFlag); } catch (PatternSyntaxException e) { setIllegalArg("The regexp for Email is Invalid regular expression."); return false; } } return notNull(pattern) && pattern.matcher(val).matches(); } //Pattern : CharSequence public boolean judge(Object value, Pattern annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value) || !isCharSequence(value)) { return false; } String val = ((CharSequence) value).toString(); if (val.isEmpty()) { return false; } Pattern.Flag[] flags = annotation.flags(); String regexp = annotation.regexp(); int intFlag = 0; for (Pattern.Flag flag : flags) { intFlag = intFlag | flag.getValue(); } java.util.regex.Pattern pattern; try { pattern = java.util.regex.Pattern.compile(regexp, intFlag); } catch (PatternSyntaxException e) { setIllegalArg("The regexp for Email is Invalid regular expression."); return false; } return notNull(pattern) && pattern.matcher(val).matches(); } //Max : CharSequence & Number public boolean judge(Object value, Max annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } final boolean isNumber = isNumber(value); final boolean isCharSequence = isCharSequence(value); if (!isCharSequence && !isNumber) { setIllegalArg("The Max is only valid for CharSequence & Number."); return false; } long max = annotation.value(); int compare; if (isNumber) { compare = numberComparator((Number) value, max, GREATER_THAN); } else { String v = ((CharSequence) value).toString().trim(); if (v.isEmpty()) { return false; } BigDecimal val = newBigDecimal(v); if (isNull(val)) { return false; } compare = val.compareTo(BigDecimal.valueOf(max)); } return lte0(compare); } //Min : CharSequence & Number public boolean judge(Object value, Min annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } final boolean isNumber = isNumber(value); final boolean isCharSequence = isCharSequence(value); if (!isCharSequence && !isNumber) { setIllegalArg("The Min is only valid for CharSequence & Number."); return false; } long min = annotation.value(); int compare; if (isNumber) { compare = numberComparator((Number) value, min, LESS_THAN); } else { String v = ((CharSequence) value).toString().trim(); if (v.isEmpty()) { return false; } BigDecimal val = newBigDecimal(v); if (isNull(val)) { return false; } compare = val.compareTo(BigDecimal.valueOf(min)); } return gte0(compare); } private int numberComparator(Number value, long limit, OptionalInt treatNanAs) { int compare; if (isLong(value)) { compare = ((Long) value).compareTo(limit); } else if (isDouble(value)) { Double val = (Double) value; OptionalInt infinity = infinityCheck(val, treatNanAs); if (infinity.isPresent()) { compare = infinity.getAsInt(); } else { compare = Double.compare(val, limit); } } else if (isFloat(value)) { Float val = (Float) value; OptionalInt infinity = infinityCheck(val, treatNanAs); if (infinity.isPresent()) { compare = infinity.getAsInt(); } else { compare = Float.compare(val, limit); } } else if (isBigDecimal(value)) { compare = ((BigDecimal) value).compareTo(BigDecimal.valueOf(limit)); } else if (isBigInteger(value)) { compare = ((BigInteger) value).compareTo(BigInteger.valueOf(limit)); } else { compare = Long.compare(value.longValue(), limit); } return compare; } private int signum(Number value, OptionalInt treatNanAs) { int signum; if (isLong(value)) { signum = Long.signum((Long) value); } else if (isInteger(value)) { signum = Integer.signum((Integer) value); } else if (isBigDecimal(value)) { signum = ((BigDecimal) value).signum(); } else if (isBigInteger(value)) { signum = ((BigInteger) value).signum(); } else if (isDouble(value)) { Double val = (Double) value; OptionalInt infinity = infinityCheck(val, treatNanAs); if (infinity.isPresent()) { signum = infinity.getAsInt(); } else { signum = val.compareTo(0D); } } else if (isFloat(value)) { Float val = (Float) value; OptionalInt infinity = infinityCheck(val, treatNanAs); if (infinity.isPresent()) { signum = infinity.getAsInt(); } else { signum = val.compareTo(0F); } } else if (isByte(value)) { signum = ((Byte) value).compareTo(BYTE_ZERO); } else if (isShort(value)) { signum = ((Short) value).compareTo(SHORT_ZERO); } else { signum = Double.compare(value.doubleValue(), 0D); } return signum; } //Negative : Number public boolean judge(Object value, Negative annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } if (!isNumber(value)) { return true; } return lt0(signum((Number) value, GREATER_THAN)); } // NegativeOrZero : Number public boolean judge(Object value, NegativeOrZero annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } if (!isNumber(value)) { return true; } return lte0(signum((Number) value, GREATER_THAN)); } //Positive : Number public boolean judge(Object value, Positive annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } if (!isNumber(value)) { return true; } return gt0(signum((Number) value, LESS_THAN)); } //PositiveOrZero : Number public boolean judge(Object value, PositiveOrZero annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } if (!isNumber(value)) { return true; } return gte0(signum((Number) value, LESS_THAN)); } public int dateComparator(Object value, boolean isTemporalAccessor, boolean isDate) { Clock clock = getClock(getDuration()); int compare; if (isTemporalAccessor) { if (value instanceof Instant) { compare = ((Instant) value).compareTo(Instant.now(clock)); } else if (value instanceof LocalDateTime) { compare = ((LocalDateTime) value).compareTo(LocalDateTime.now(clock)); } else if (value instanceof LocalDate) { compare = ((LocalDate) value).compareTo(LocalDate.now(clock)); } else if (value instanceof LocalTime) { compare = ((LocalTime) value).compareTo(LocalTime.now(clock)); } else if (value instanceof MonthDay) { compare = ((MonthDay) value).compareTo(MonthDay.now(clock)); } else if (value instanceof HijrahDate) { compare = ((HijrahDate) value).compareTo(HijrahDate.now(clock)); } else if (value instanceof JapaneseDate) { compare = ((JapaneseDate) value).compareTo(JapaneseDate.now(clock)); } else if (value instanceof MinguoDate) { compare = ((MinguoDate) value).compareTo(MinguoDate.now(clock)); } else if (value instanceof OffsetDateTime) { compare = ((OffsetDateTime) value).compareTo(OffsetDateTime.now(clock)); } else if (value instanceof OffsetTime) { compare = ((OffsetTime) value).compareTo(OffsetTime.now(clock)); } else if (value instanceof ThaiBuddhistDate) { compare = ((ThaiBuddhistDate) value).compareTo(ThaiBuddhistDate.now(clock)); } else if (value instanceof Year) { compare = ((Year) value).compareTo(Year.now(clock)); } else if (value instanceof YearMonth) { compare = ((YearMonth) value).compareTo(YearMonth.now(clock)); } else if (value instanceof ZonedDateTime) { compare = ((ZonedDateTime) value).compareTo(ZonedDateTime.now(clock)); } else { compare = -2; } } else if (isDate) { Date val = (Date) value; compare = val.toInstant().compareTo(Instant.now(clock)); } else { Calendar val = (Calendar) value; compare = val.toInstant().compareTo(Instant.now(clock)); } return compare; } //Future : TemporalAccessor ,java.util.Date,java.util.Calendar public boolean judge(Object value, Future annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } final boolean isTemporalAccessor = isTemporalAccessor(value); final boolean isDate = isDate(value); final boolean isCalendar = isCalendar(value); if (!isTemporalAccessor && !isDate && !isCalendar) { setIllegalArg("Future is only for TemporalAccessor & Date & Calendar"); return false; } int compare = dateComparator(value, isTemporalAccessor, isDate); if (-2 == compare) { setIllegalArg(value.getClass().toString() + " is not a supported date class temporarily."); return false; } //compare > 0 return gt0(compare); } //FutureOrPresent : TemporalAccessor ,java.util.Date,java.util.Calendar public boolean judge(Object value, FutureOrPresent annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } final boolean isTemporalAccessor = isTemporalAccessor(value); final boolean isDate = isDate(value); final boolean isCalendar = isCalendar(value); if (!isTemporalAccessor && !isDate && !isCalendar) { setIllegalArg("FutureOrPresent is only for TemporalAccessor & Date & Calendar"); return false; } int compare = dateComparator(value, isTemporalAccessor, isDate); if (-2 == compare) { setIllegalArg(value.getClass().toString() + " is not a supported date class temporarily."); return false; } //compare >= 0 return gte0(compare); } //Past : TemporalAccessor ,java.util.Date,java.util.Calendar public boolean judge(Object value, Past annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } final boolean isTemporalAccessor = isTemporalAccessor(value); final boolean isDate = isDate(value); final boolean isCalendar = isCalendar(value); if (!isTemporalAccessor && !isDate && !isCalendar) { setIllegalArg("Past is only for TemporalAccessor & Date & Calendar"); return false; } int compare = dateComparator(value, isTemporalAccessor, isDate); if (-2 == compare) { setIllegalArg(value.getClass().toString() + " is not a supported date class temporarily."); return false; } //compare < 0 return lt0(compare); } //PastOrPresent : TemporalAccessor ,java.util.Date,java.util.Calendar public boolean judge(Object value, PastOrPresent annotation) { if (isNull(annotation)) { return true; } setVerify(annotation.message()); if (isNull(value)) { return false; } final boolean isTemporalAccessor = isTemporalAccessor(value); final boolean isDate = isDate(value); final boolean isCalendar = isCalendar(value); if (!isTemporalAccessor && !isDate && !isCalendar) { setIllegalArg("PastOrPresent is only for TemporalAccessor & Date & Calendar"); return false; } int compare = dateComparator(value, isTemporalAccessor, isDate); if (-2 == compare) { setIllegalArg(value.getClass().toString() + " is not a supported date class temporarily."); return false; } //compare <= 0 return lte0(compare); } }