/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sis.filter;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import java.util.Calendar;
import java.time.Instant;
import java.time.LocalTime;
import java.time.OffsetTime;
import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.chrono.ChronoLocalDate;
import java.time.chrono.ChronoLocalDateTime;
import java.time.chrono.ChronoZonedDateTime;
import java.time.temporal.ChronoField;
import java.time.temporal.Temporal;
import org.apache.sis.math.Fraction;
import org.apache.sis.util.ArgumentChecks;

// Branch-dependent imports
import org.opengis.filter.MatchAction;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.BinaryComparisonOperator;
import org.opengis.filter.FilterVisitor;


/**
 * Comparison operators between two values. Values are converted to the same before comparison, using a widening conversion
 * (for example from {@link Integer} to {@link Double}). If values can not be compared because they can not be converted to
 * a common type, or because a value is null or NaN, then the comparison result if {@code false}. A consequence of this rule
 * is that the two conditions {@literal A < B} and {@literal A ≧ B} may be false in same time.
 *
 * <p>If one operand is a collection, all collection elements may be compared to the other value.
 * Null elements in the collection (not to be confused with null operands) are ignored.
 * If both operands are collections, current implementation returns {@code false}.</p>
 *
 * <p>Comparisons between temporal objects are done with {@code isBefore(…)} or {@code isAfter(…)} methods when they
 * have a different semantic than the {@code compareTo(…)} methods. If the two temporal objects are not of the same
 * type, only the fields that are common two both types are compared. For example comparison between {@code LocalDate}
 * and {@code LocalDateTime} ignores the time fields.</p>
 *
 * <p>Comparisons of numerical types shall be done by overriding one of the {@code applyAs…} methods and
 * returning 0 if {@code false} or 1 if {@code true}. Comparisons of other types is done by overriding
 * the {@code compare(…)} methods.</p>
 *
 * @author  Johann Sorel (Geomatys)
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.1
 * @since   1.1
 * @module
 */
abstract class ComparisonFunction extends BinaryFunction implements BinaryComparisonOperator {
    /**
     * For cross-version compatibility.
     */
    private static final long serialVersionUID = 1228683039737814926L;

    /**
     * Specifies whether comparisons are case sensitive.
     */
    private final boolean isMatchingCase;

    /**
     * Specifies how the comparisons shall be evaluated for a collection of values.
     * Values can be ALL, ANY or ONE.
     */
    private final MatchAction matchAction;

    /**
     * Creates a new comparator.
     *
     * @param  expression1     the first of the two expressions to be used by this comparator.
     * @param  expression2     the second of the two expressions to be used by this comparator.
     * @param  isMatchingCase  specifies whether comparisons are case sensitive.
     * @param  matchAction     specifies how the comparisons shall be evaluated for a collection of values.
     */
    ComparisonFunction(final Expression expression1, final Expression expression2, final boolean isMatchingCase, final MatchAction matchAction) {
        super(expression1, expression2);
        this.isMatchingCase = isMatchingCase;
        this.matchAction = matchAction;
        ArgumentChecks.ensureNonNull("matchAction", matchAction);
    }

    /**
     * Returns whether comparisons are case sensitive.
     */
    @Override
    public final boolean isMatchingCase() {
        return isMatchingCase;
    }

    /**
     * Returns how the comparisons are evaluated for a collection of values.
     */
    @Override
    public final MatchAction getMatchAction() {
        return matchAction;
    }

    /**
     * Takes in account the additional properties in hash code calculation.
     */
    @Override
    public final int hashCode() {
        return super.hashCode() + Boolean.hashCode(isMatchingCase) + 61 * matchAction.hashCode();
    }

    /**
     * Takes in account the additional properties in object comparison.
     */
    @Override
    public final boolean equals(final Object obj) {
        if (super.equals(obj)) {
            final ComparisonFunction other = (ComparisonFunction) obj;
            return other.isMatchingCase == isMatchingCase && matchAction.equals(other.matchAction);
        }
        return false;
    }

    /**
     * Determines if the test(s) represented by this filter passes with the given operands.
     * Values of {@link #expression1} and {@link #expression2} can be two single values,
     * or at most one expression can produce a collection.
     */
    @Override
    public final boolean evaluate(final Object candidate) {
        final Object left = expression1.evaluate(candidate);
        if (left != null) {
            final Object right = expression2.evaluate(candidate);
            if (right != null) {
                final Iterable<?> collection;
                final boolean collectionFirst = (left instanceof Iterable<?>);
                if (collectionFirst) {
                    if (right instanceof Iterable<?>) {
                        // Current implementation does not support collection on both sides. See class javadoc.
                        return false;
                    }
                    collection = (Iterable<?>) left;
                } else if (right instanceof Iterable<?>) {
                    collection = (Iterable<?>) right;
                } else {
                    return evaluate(left, right);
                }
                /*
                 * At this point, exactly one of the operands is a collection. It may be the left or right one.
                 * All values in the collection may be compared to the other value until match condition is met.
                 * Null elements in the collection are ignored.
                 */
                boolean match = false;
                for (final Object element : collection) {
                    if (element != null) {
                        final boolean pass;
                        if (collectionFirst) {
                            pass = evaluate(element, right);
                        } else {
                            pass = evaluate(left, element);
                        }
                        switch (matchAction) {
                            default: return false;              // Unknown enumeration.
                            case ALL: {
                                if (!pass) return false;
                                match = true;                   // Remember that we have at least 1 value.
                                break;
                            }
                            case ANY: {
                                if (pass) return true;
                                break;                          // `match` still false since no match.
                            }
                            case ONE: {
                                if (pass) {
                                    if (match) return false;    // If a value has been found previously.
                                    match = true;               // Remember that we have exactly one value.
                                }
                            }
                        }
                    }
                }
                return match;
            }
        }
        return false;
    }

    /**
     * Compares the given objects. If both values are numerical, then this method delegates to an {@code applyAs…} method.
     * For other kind of objects, this method delegates to a {@code compare(…)} method. If the two objects are not of the
     * same type, then the less accurate one is converted to the most accurate type if possible.
     *
     * @param  left   the first object to compare. Must be non-null.
     * @param  right  the second object to compare. Must be non-null.
     */
    @SuppressWarnings("null")
    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 ComparisonFunction 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 comparaisons 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;
    }

    /**
     * Converts a legacy {@code Date} object to an object from the {@link java.time} package.
     * We performs this conversion before to compare to {@code Date} instances that are not of
     * the same class, because the {@link Date#compareTo(Date)} method in such case is not well
     * defined.
     */
    private static Temporal fromLegacy(final Date value) {
        if (value instanceof java.sql.Timestamp) {
            return ((java.sql.Timestamp) value).toLocalDateTime();
        } else if (value instanceof java.sql.Date) {
            return ((java.sql.Date) value).toLocalDate();
        } else if (value instanceof java.sql.Time) {
            return ((java.sql.Time) value).toLocalTime();
        } else {
            // Implementation of above toFoo() methods use system default time zone.
            return LocalDateTime.ofInstant(value.toInstant(), ZoneId.systemDefault());
        }
    }

    /**
     * Converts the given object to an {@link Instant}, or returns {@code null} if unconvertible.
     * This method handles a few types from the {@link java.time} package and legacy types like
     * {@link Date} (with a special case for SQL dates) and {@link Calendar}.
     */
    static Instant toInstant(final Object value) {
        if (value instanceof Instant) {
            return (Instant) value;
        } else if (value instanceof OffsetDateTime) {
            return ((OffsetDateTime) value).toInstant();
        } else if (value instanceof ChronoZonedDateTime) {
            return ((ChronoZonedDateTime) value).toInstant();
        } else if (value instanceof Date) {
            try {
                return ((Date) value).toInstant();
            } catch (UnsupportedOperationException e) {
                /*
                 * java.sql.Date and java.sql.Time can not be converted to Instant because a part
                 * of their coordinates on the timeline is undefined.  For example in the case of
                 * java.sql.Date the hours, minutes and seconds are unspecified (which is not the
                 * same thing than assuming that those values are zero).
                 */
            }
        } else if (value instanceof Calendar) {
            return ((Calendar) value).toInstant();
        }
        return null;
    }

    /**
     * Converts the given object to an {@link OffsetDateTime}, or returns {@code null} if unconvertible.
     */
    private static OffsetDateTime toOffsetDateTime(final Object value) {
        if (value instanceof OffsetDateTime) {
            return (OffsetDateTime) value;
        } else if (value instanceof ZonedDateTime) {
            return ((ZonedDateTime) value).toOffsetDateTime();
        } else {
            return null;
        }
    }

    /**
     * Converts the given object to a {@link ChronoLocalDateTime}, or returns {@code null} if unconvertible.
     * This method handles the case of legacy SQL {@link java.sql.Timestamp} objects.
     * Conversion may lost timezone information.
     */
    private static ChronoLocalDateTime<?> toLocalDateTime(final Object value) {
        if (value instanceof ChronoLocalDateTime<?>) {
            return (ChronoLocalDateTime<?>) value;
        } else if (value instanceof ChronoZonedDateTime) {
            ignoringField(ChronoField.OFFSET_SECONDS);
            return ((ChronoZonedDateTime) value).toLocalDateTime();
        } else if (value instanceof OffsetDateTime) {
            ignoringField(ChronoField.OFFSET_SECONDS);
            return ((OffsetDateTime) value).toLocalDateTime();
        } else if (value instanceof java.sql.Timestamp) {
            return ((java.sql.Timestamp) value).toLocalDateTime();
        } else {
            return null;
        }
    }

    /**
     * Converts the given object to a {@link ChronoLocalDate}, or returns {@code null} if unconvertible.
     * This method handles the case of legacy SQL {@link java.sql.Date} objects.
     * Conversion may lost timezone information and time fields.
     */
    private static ChronoLocalDate toLocalDate(final Object value) {
        if (value instanceof ChronoLocalDate) {
            return (ChronoLocalDate) value;
        } else if (value instanceof ChronoLocalDateTime) {
            ignoringField(ChronoField.SECOND_OF_DAY);
            return ((ChronoLocalDateTime) value).toLocalDate();
        } else if (value instanceof ChronoZonedDateTime) {
            ignoringField(ChronoField.SECOND_OF_DAY);
            return ((ChronoZonedDateTime) value).toLocalDate();
        } else if (value instanceof OffsetDateTime) {
            ignoringField(ChronoField.SECOND_OF_DAY);
            return ((OffsetDateTime) value).toLocalDate();
        } else if (value instanceof java.sql.Date) {
            return ((java.sql.Date) value).toLocalDate();
        } else {
            return null;
        }
    }

    /**
     * Converts the given object to a {@link LocalTime}, or returns {@code null} if unconvertible.
     * This method handles the case of legacy SQL {@link java.sql.Time} objects.
     * Conversion may lost timezone information.
     */
    private static LocalTime toLocalTime(final Object value) {
        if (value instanceof LocalTime) {
            return (LocalTime) value;
        } else if (value instanceof OffsetTime) {
            ignoringField(ChronoField.OFFSET_SECONDS);
            return ((OffsetTime) value).toLocalTime();
        } else if (value instanceof java.sql.Time) {
            return ((java.sql.Time) value).toLocalTime();
        } else {
            return null;
        }
    }

    /**
     * Invoked when a conversion cause a field to be ignored. For example if a "date+time" object is compared
     * with a "date" object, the "time" field is ignored. Expected values are:
     *
     * <ul>
     *   <li>{@link ChronoField#OFFSET_SECONDS}: time zone is ignored.</li>
     *   <li>{@link ChronoField#SECOND_OF_DAY}:  time of dat and time zone are ignored.</li>
     * </ul>
     *
     * @param  field  the field which is ignored.
     *
     * @see <a href="https://issues.apache.org/jira/browse/SIS-460">SIS-460</a>
     */
    private static void ignoringField(final ChronoField field) {
        // TODO
    }

    /**
     * Converts the boolean result as an integer for use as a return value of the {@code applyAs…} methods.
     * This is a helper class for subclasses.
     */
    private static Number number(final boolean result) {
        return result ? 1 : 0;
    }

    /**
     * Converts the result of {@link Comparable#compareTo(Object)}.
     */
    protected abstract boolean fromCompareTo(int result);

    /**
     * Compares two times with time-zone information. Implementations shall not use {@code compareTo(…)} because
     * that method compares more information than desired in order to ensure consistency with {@code equals(…)}.
     */
    protected abstract boolean compare(OffsetTime left, OffsetTime right);

    /**
     * Compares two dates with time-zone information. Implementations shall not use {@code compareTo(…)} because
     * that method compares more information than desired in order to ensure consistency with {@code equals(…)}.
     */
    protected abstract boolean compare(OffsetDateTime left, OffsetDateTime right);

    /**
     * Compares two dates without time-of-day and time-zone information. Implementations shall not use
     * {@code compareTo(…)} because that method also compares chronology, which is not desired for the
     * purpose of "is before" or "is after" comparison functions.
     */
    protected abstract boolean compare(ChronoLocalDate left, ChronoLocalDate right);

    /**
     * Compares two dates without time-zone information. Implementations shall not use {@code compareTo(…)}
     * because that method also compares chronology, which is not desired for the purpose of "is before" or
     * "is after" comparison functions.
     */
    protected abstract boolean compare(ChronoLocalDateTime<?> left, ChronoLocalDateTime<?> right);

    /**
     * Compares two dates with time-zone information. Implementations shall not use {@code compareTo(…)}
     * because that method also compares chronology, which is not desired for the purpose of "is before"
     * or "is after" comparison functions.
     */
    protected abstract boolean compare(ChronoZonedDateTime<?> left, ChronoZonedDateTime<?> right);

    /** Delegates to {@link BigDecimal#compareTo(BigDecimal)} and interprets the result with {@link #fromCompareTo(int)}. */
    @Override protected final Number applyAsDecimal (BigDecimal left, BigDecimal right) {return number(fromCompareTo(left.compareTo(right)));}
    @Override protected final Number applyAsInteger (BigInteger left, BigInteger right) {return number(fromCompareTo(left.compareTo(right)));}
    @Override protected final Number applyAsFraction(Fraction   left, Fraction   right) {return number(fromCompareTo(left.compareTo(right)));}


    /**
     * The {@value #NAME} {@literal (<)} filter.
     */
    static final class LessThan extends ComparisonFunction implements org.opengis.filter.PropertyIsLessThan {
        /** For cross-version compatibility during (de)serialization. */
        private static final long serialVersionUID = 6126039112844823196L;

        /** Creates a new filter for the {@value #NAME} operation. */
        LessThan(Expression expression1, Expression expression2, boolean isMatchingCase, MatchAction matchAction) {
            super(expression1, expression2, isMatchingCase, matchAction);
        }

        /** Identification of this operation. */
        @Override protected String getName() {return NAME;}
        @Override protected char   symbol()  {return '<';}

        /** Converts {@link Comparable#compareTo(Object)} result to this filter result. */
        @Override protected boolean fromCompareTo(final int result) {return result < 0;}

        /** Performs the comparison and returns the result as 0 (false) or 1 (true). */
        @Override protected Number  applyAsDouble(double                 left, double                 right) {return number(left < right);}
        @Override protected Number  applyAsLong  (long                   left, long                   right) {return number(left < right);}
        @Override protected boolean compare      (OffsetTime             left, OffsetTime             right) {return left.isBefore(right);}
        @Override protected boolean compare      (OffsetDateTime         left, OffsetDateTime         right) {return left.isBefore(right);}
        @Override protected boolean compare      (ChronoLocalDate        left, ChronoLocalDate        right) {return left.isBefore(right);}
        @Override protected boolean compare      (ChronoLocalDateTime<?> left, ChronoLocalDateTime<?> right) {return left.isBefore(right);}
        @Override protected boolean compare      (ChronoZonedDateTime<?> left, ChronoZonedDateTime<?> right) {return left.isBefore(right);}

        /** Implementation of the visitor pattern (not used by Apache SIS). */
        @Override public Object accept(FilterVisitor visitor, Object extraData) {
            return visitor.visit(this, extraData);
        }
    }


    /**
     * The {@value #NAME} (≤) filter.
     */
    static final class LessThanOrEqualTo extends ComparisonFunction implements org.opengis.filter.PropertyIsLessThanOrEqualTo {
        /** For cross-version compatibility during (de)serialization. */
        private static final long serialVersionUID = 6357459227911760871L;

        /** Creates a new filter for the {@value #NAME} operation. */
        LessThanOrEqualTo(Expression expression1, Expression expression2, boolean isMatchingCase, MatchAction matchAction) {
            super(expression1, expression2, isMatchingCase, matchAction);
        }

        /** Identification of this operation. */
        @Override protected String getName() {return NAME;}
        @Override protected char   symbol()  {return '≤';}

        /** Converts {@link Comparable#compareTo(Object)} result to this filter result. */
        @Override protected boolean fromCompareTo(final int result) {return result <= 0;}

        /** Performs the comparison and returns the result as 0 (false) or 1 (true). */
        @Override protected Number  applyAsDouble(double                 left, double                 right) {return number(left <= right);}
        @Override protected Number  applyAsLong  (long                   left, long                   right) {return number(left <= right);}
        @Override protected boolean compare      (OffsetTime             left, OffsetTime             right) {return !left.isAfter(right);}
        @Override protected boolean compare      (OffsetDateTime         left, OffsetDateTime         right) {return !left.isAfter(right);}
        @Override protected boolean compare      (ChronoLocalDate        left, ChronoLocalDate        right) {return !left.isAfter(right);}
        @Override protected boolean compare      (ChronoLocalDateTime<?> left, ChronoLocalDateTime<?> right) {return !left.isAfter(right);}
        @Override protected boolean compare      (ChronoZonedDateTime<?> left, ChronoZonedDateTime<?> right) {return !left.isAfter(right);}

        /** Implementation of the visitor pattern (not used by Apache SIS). */
        @Override public Object accept(FilterVisitor visitor, Object extraData) {
            return visitor.visit(this, extraData);
        }
    }


    /**
     * The {@value #NAME} {@literal (>)} filter.
     */
    static final class GreaterThan extends ComparisonFunction implements org.opengis.filter.PropertyIsGreaterThan {
        /** For cross-version compatibility during (de)serialization. */
        private static final long serialVersionUID = 8605517892232632586L;

        /** Creates a new filter for the {@value #NAME} operation. */
        GreaterThan(Expression expression1, Expression expression2, boolean isMatchingCase, MatchAction matchAction) {
            super(expression1, expression2, isMatchingCase, matchAction);
        }

        /** Identification of this operation. */
        @Override protected String getName() {return NAME;}
        @Override protected char   symbol()  {return '>';}

        /** Converts {@link Comparable#compareTo(Object)} result to this filter result. */
        @Override protected boolean fromCompareTo(final int result) {return result > 0;}

        /** Performs the comparison and returns the result as 0 (false) or 1 (true). */
        @Override protected Number  applyAsDouble(double                 left, double                 right) {return number(left > right);}
        @Override protected Number  applyAsLong  (long                   left, long                   right) {return number(left > right);}
        @Override protected boolean compare      (OffsetTime             left, OffsetTime             right) {return left.isAfter(right);}
        @Override protected boolean compare      (OffsetDateTime         left, OffsetDateTime         right) {return left.isAfter(right);}
        @Override protected boolean compare      (ChronoLocalDate        left, ChronoLocalDate        right) {return left.isAfter(right);}
        @Override protected boolean compare      (ChronoLocalDateTime<?> left, ChronoLocalDateTime<?> right) {return left.isAfter(right);}
        @Override protected boolean compare      (ChronoZonedDateTime<?> left, ChronoZonedDateTime<?> right) {return left.isAfter(right);}

        /** Implementation of the visitor pattern (not used by Apache SIS). */
        @Override public Object accept(FilterVisitor visitor, Object extraData) {
            return visitor.visit(this, extraData);
        }
    }


    /**
     * The {@value #NAME} (≥) filter.
     */
    static final class GreaterThanOrEqualTo extends ComparisonFunction implements org.opengis.filter.PropertyIsGreaterThanOrEqualTo {
        /** For cross-version compatibility during (de)serialization. */
        private static final long serialVersionUID = 1514185657159141882L;

        /** Creates a new filter for the {@value #NAME} operation. */
        GreaterThanOrEqualTo(Expression expression1, Expression expression2, boolean isMatchingCase, MatchAction matchAction) {
            super(expression1, expression2, isMatchingCase, matchAction);
        }

        /** Identification of this operation. */
        @Override protected String getName() {return NAME;}
        @Override protected char   symbol()  {return '≥';}

        /** Converts {@link Comparable#compareTo(Object)} result to this filter result. */
        @Override protected boolean fromCompareTo(final int result) {return result >= 0;}

        /** Performs the comparison and returns the result as 0 (false) or 1 (true). */
        @Override protected Number  applyAsDouble(double                 left, double                 right) {return number(left >= right);}
        @Override protected Number  applyAsLong  (long                   left, long                   right) {return number(left >= right);}
        @Override protected boolean compare      (OffsetTime             left, OffsetTime             right) {return !left.isBefore(right);}
        @Override protected boolean compare      (OffsetDateTime         left, OffsetDateTime         right) {return !left.isBefore(right);}
        @Override protected boolean compare      (ChronoLocalDate        left, ChronoLocalDate        right) {return !left.isBefore(right);}
        @Override protected boolean compare      (ChronoLocalDateTime<?> left, ChronoLocalDateTime<?> right) {return !left.isBefore(right);}
        @Override protected boolean compare      (ChronoZonedDateTime<?> left, ChronoZonedDateTime<?> right) {return !left.isBefore(right);}

        /** Implementation of the visitor pattern (not used by Apache SIS). */
        @Override public Object accept(FilterVisitor visitor, Object extraData) {
            return visitor.visit(this, extraData);
        }
    }


    /**
     * The {@value #NAME} (=) filter.
     */
    static final class EqualTo extends ComparisonFunction implements org.opengis.filter.PropertyIsEqualTo {
        /** For cross-version compatibility during (de)serialization. */
        private static final long serialVersionUID = 8502612221498749667L;

        /** Creates a new filter for the {@value #NAME} operation. */
        EqualTo(Expression expression1, Expression expression2, boolean isMatchingCase, MatchAction matchAction) {
            super(expression1, expression2, isMatchingCase, matchAction);
        }

        /** Identification of this operation. */
        @Override protected String getName() {return NAME;}
        @Override protected char   symbol()  {return '=';}

        /** Converts {@link Comparable#compareTo(Object)} result to this filter result. */
        @Override protected boolean fromCompareTo(final int result) {return result == 0;}

        /** Performs the comparison and returns the result as 0 (false) or 1 (true). */
        @Override protected Number  applyAsDouble(double                 left, double                 right) {return number(left == right);}
        @Override protected Number  applyAsLong  (long                   left, long                   right) {return number(left == right);}
        @Override protected boolean compare      (OffsetTime             left, OffsetTime             right) {return left.isEqual(right);}
        @Override protected boolean compare      (OffsetDateTime         left, OffsetDateTime         right) {return left.isEqual(right);}
        @Override protected boolean compare      (ChronoLocalDate        left, ChronoLocalDate        right) {return left.isEqual(right);}
        @Override protected boolean compare      (ChronoLocalDateTime<?> left, ChronoLocalDateTime<?> right) {return left.isEqual(right);}
        @Override protected boolean compare      (ChronoZonedDateTime<?> left, ChronoZonedDateTime<?> right) {return left.isEqual(right);}

        /** Implementation of the visitor pattern (not used by Apache SIS). */
        @Override public Object accept(FilterVisitor visitor, Object extraData) {
            return visitor.visit(this, extraData);
        }
    }


    /**
     * The {@value #NAME} (≠) filter.
     */
    static final class NotEqualTo extends ComparisonFunction implements org.opengis.filter.PropertyIsNotEqualTo {
        /** For cross-version compatibility during (de)serialization. */
        private static final long serialVersionUID = -3295957142249035362L;

        /** Creates a new filter for the {@value #NAME} operation. */
        NotEqualTo(Expression expression1, Expression expression2, boolean isMatchingCase, MatchAction matchAction) {
            super(expression1, expression2, isMatchingCase, matchAction);
        }

        /** Identification of this operation. */
        @Override protected String getName() {return NAME;}
        @Override protected char   symbol()  {return '≠';}

        /** Converts {@link Comparable#compareTo(Object)} result to this filter result. */
        @Override protected boolean fromCompareTo(final int result) {return result != 0;}

        /** Performs the comparison and returns the result as 0 (false) or 1 (true). */
        @Override protected Number  applyAsDouble(double                 left, double                 right) {return number(left != right);}
        @Override protected Number  applyAsLong  (long                   left, long                   right) {return number(left != right);}
        @Override protected boolean compare      (OffsetTime             left, OffsetTime             right) {return !left.isEqual(right);}
        @Override protected boolean compare      (OffsetDateTime         left, OffsetDateTime         right) {return !left.isEqual(right);}
        @Override protected boolean compare      (ChronoLocalDate        left, ChronoLocalDate        right) {return !left.isEqual(right);}
        @Override protected boolean compare      (ChronoLocalDateTime<?> left, ChronoLocalDateTime<?> right) {return !left.isEqual(right);}
        @Override protected boolean compare      (ChronoZonedDateTime<?> left, ChronoZonedDateTime<?> right) {return !left.isEqual(right);}

        /** Implementation of the visitor pattern (not used by Apache SIS). */
        @Override public Object accept(FilterVisitor visitor, Object extraData) {
            return visitor.visit(this, extraData);
        }
    }
}
