private boolean evaluate()

in endorsed/src/org.apache.sis.feature/main/org/apache/sis/filter/ComparisonFilter.java [238:342]


    private boolean evaluate(Object left, Object right) {
        /*
         * For numbers, the apply(…) method inherited from parent class will delegate to specialized methods like
         * applyAsDouble(…). All implementations of those specialized methods in ComparisonFilter return integer,
         * so call to intValue() will not cause information lost.
         */
        if (left instanceof Number && right instanceof Number) {
            final Number r = apply((Number) left, (Number) right);
            if (r != null) return r.intValue() != 0;
        }
        /*
         * For legacy java.util.Date, the compareTo(…) method is consistent only for dates of the same class.
         * Otherwise A.compareTo(B) and B.compareTo(A) are inconsistent if one object is a java.util.Date and
         * the other object is a java.sql.Timestamp. In such case, we compare the dates as java.time objects.
         */
        if (left instanceof Date && right instanceof Date) {
            if (left.getClass() == right.getClass()) {
                return fromCompareTo(((Date) left).compareTo((Date) right));
            }
            left  = fromLegacy((Date) left);
            right = fromLegacy((Date) right);
        }
        /*
         * Temporal objects have complex conversion rules. We take Instant as the most accurate and unambiguous type.
         * So if at least one value is an Instant, try to unconditionally promote the other value to an Instant too.
         * This conversion will fail if the other object has some undefined fields; for example java.sql.Date has no
         * time fields (we do not assume that the values of those fields are zero).
         *
         * OffsetTime and OffsetDateTime are final classes that do not implement a java.time.chrono interface.
         * Note that OffsetDateTime is convertible into OffsetTime by dropping the date fields, but we do not
         * (for now) perform comparisons that would ignore the date fields of an operand.
         */
        if (left instanceof Temporal || right instanceof Temporal) {        // Use || because an operand may be Date.
            if (left instanceof Instant) {
                final Instant t = toInstant(right);
                if (t != null) return fromCompareTo(((Instant) left).compareTo(t));
            } else if (right instanceof Instant) {
                final Instant t = toInstant(left);
                if (t != null) return fromCompareTo(t.compareTo((Instant) right));
            } else if (left instanceof OffsetDateTime) {
                final OffsetDateTime t = toOffsetDateTime(right);
                if (t != null) return compare((OffsetDateTime) left, t);
            } else if (right instanceof OffsetDateTime) {
                final OffsetDateTime t = toOffsetDateTime(left);
                if (t != null) return compare(t, (OffsetDateTime) right);
            } else if (left instanceof OffsetTime && right instanceof OffsetTime) {
                return compare((OffsetTime) left, (OffsetTime) right);
            }
            /*
             * Comparisons of temporal objects implementing java.time.chrono interfaces. We need to check the most
             * complete types first. If the type are different, we reduce to the type of the less smallest operand.
             * For example if an operand is a date+time and the other operand is only a date, then the time fields
             * will be ignored and a warning will be reported.
             */
            if (left instanceof ChronoLocalDateTime<?>) {
                final ChronoLocalDateTime<?> t = toLocalDateTime(right);
                if (t != null) return compare((ChronoLocalDateTime<?>) left, t);
            } else if (right instanceof ChronoLocalDateTime<?>) {
                final ChronoLocalDateTime<?> t = toLocalDateTime(left);
                if (t != null) return compare(t, (ChronoLocalDateTime<?>) right);
            }
            if (left instanceof ChronoLocalDate) {
                final ChronoLocalDate t = toLocalDate(right);
                if (t != null) return compare((ChronoLocalDate) left, t);
            } else if (right instanceof ChronoLocalDate) {
                final ChronoLocalDate t = toLocalDate(left);
                if (t != null) return compare(t, (ChronoLocalDate) right);
            }
            if (left instanceof LocalTime) {
                final LocalTime t = toLocalTime(right);
                if (t != null) return fromCompareTo(((LocalTime) left).compareTo(t));
            } else if (right instanceof LocalTime) {
                final LocalTime t = toLocalTime(left);
                if (t != null) return fromCompareTo(t.compareTo((LocalTime) right));
            }
        }
        /*
         * Test character strings only after all specialized types have been tested. The intent is that if an
         * object implements both CharSequence and a specialized interface, they have been compared as value
         * objects before to be compared as strings.
         */
        if (left instanceof CharSequence || right instanceof CharSequence) {            // Really ||, not &&.
            final String s1 = left.toString();
            final String s2 = right.toString();
            final int result;
            if (isMatchingCase) {
                result = s1.compareTo(s2);
            } else {
                result = s1.compareToIgnoreCase(s2);        // TODO: use Collator for taking locale in account.
            }
            return fromCompareTo(result);
        }
        /*
         * Comparison using `compareTo` method should be last because it does not take in account
         * the `isMatchingCase` flag and because the semantic is different than < or > comparator
         * for numbers and dates.
         */
        if (left.getClass() == right.getClass() && (left instanceof Comparable<?>)) {
            @SuppressWarnings("unchecked")
            final int result = ((Comparable) left).compareTo(right);
            return fromCompareTo(result);
        }
        // TODO: report a warning for non-comparable objects.
        return false;
    }