001/*
002 *    GeoAPI - Java interfaces for OGC/ISO standards
003 *    Copyright © 2006-2023 Open Geospatial Consortium, Inc.
004 *    http://www.geoapi.org
005 *
006 *    Licensed under the Apache License, Version 2.0 (the "License");
007 *    you may not use this file except in compliance with the License.
008 *    You may obtain a copy of the License at
009 *
010 *        http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *    Unless required by applicable law or agreed to in writing, software
013 *    distributed under the License is distributed on an "AS IS" BASIS,
014 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 *    See the License for the specific language governing permissions and
016 *    limitations under the License.
017 */
018package org.opengis.filter;
019
020import java.util.List;
021import java.util.Comparator;
022import org.opengis.annotation.UML;
023
024import static org.opengis.annotation.Obligation.MANDATORY;
025import static org.opengis.annotation.Specification.ISO_19143;
026
027
028/**
029 * Properties whose values shall be used to order the set of resources that satisfy a filter expression.
030 * {@code SortBy} provides an entry point to invoke the sorting mechanism of the filter expression processor.
031 * The sorting mechanism is not specified. The only requirement is that the sort sequence shall be consistent,
032 * given the same data set and sort request, between consecutive invocations of the sort.
033 *
034 * @author  Martin Desruisseaux (Geomatys)
035 * @version 3.1
036 *
037 * @param  <R>  the type of resources (e.g. {@link org.opengis.feature.Feature}) to sort.
038 *
039 * @since 3.1
040 */
041@UML(identifier="SortBy", specification=ISO_19143)
042public interface SortBy<R> extends Comparator<R> {
043    /**
044     * The properties whose values are used for sorting. The list shall have a minimum of one element.
045     * In the event that multiple elements exist, the sequence of the {@code SortProperty} elements
046     * determines the order of ordering.
047     *
048     * @return properties whose values are used for sorting.
049     */
050    @UML(identifier="sortProperty", obligation=MANDATORY, specification=ISO_19143)
051    List<SortProperty<R>> getSortProperties();
052
053    /**
054     * Compares two resources for order. Returns a negative number if {@code r1} should be sorted before {@code r2},
055     * a positive number if {@code r2} should be after {@code r1}, or 0 if both resources are equal.
056     * The ordering of null resources or null property values is unspecified.
057     *
058     * <p>The comparison shall be consistent (ignoring unspecified aspects such as null values)
059     * with a comparison done "manually" by the following code:</p>
060     *
061     * {@snippet lang="java" :
062     * for (SortProperty<R> p : getSortProperties()) {
063     *     int c = p.compare(r1, r2);
064     *     if (c != 0) return c;
065     * }
066     * return 0;
067     * }
068     *
069     * <p>In order words, it shall be possible for the users to build their own SQL (or other language) query
070     * using above information and get the same results without invoking this {@code compare(…)} method.</p>
071     *
072     * @param  r1  the first resource to compare.
073     * @param  r2  the second resource to compare.
074     * @return negative if the first resource is before the second, positive for the converse, or 0 if equal.
075     * @throws InvalidFilterValueException if an expression cannot be applied on the given resources.
076     * @throws ClassCastException if the types of {@linkplain ValueReference#apply(Object) property values}
077     *         prevent them from being compared by this comparator.
078     *
079     * @see SortProperty#compare(Object, Object)
080     */
081    @Override
082    default int compare(final R r1, final R r2) {
083        for (final SortProperty<R> p : getSortProperties()) {
084            final int c = p.compare(r1, r2);
085            if (c != 0) return c;
086        }
087        return 0;
088    }
089}