/*
 * 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.
 */

#ifndef _DECAF_UTIL_COMPARATOR_H_
#define _DECAF_UTIL_COMPARATOR_H_

#include <decaf/util/Config.h>

namespace decaf{
namespace util{

    /**
     * A comparison function, which imposes a total ordering on some collection
     * of objects. Comparators can be passed to a sort method (such as
     * Collections.sort) to allow precise control over the sort order. Comparators
     * can also be used to control the order of certain data structures.
     *
     * The ordering imposed by a Comparator c on a set of elements S is said to
     * be consistent with equals if and only if
     * ( compare( e1, e2) == 0 ) has the same boolean value as ( e1 == e2 ) for
     * every e1 and e2 in S.
     */
    template<typename T>
    class Comparator
    {
    public:

        virtual ~Comparator() {}

        /**
         * Compares its two arguments for order. Returns a negative integer, zero,
         * or a positive integer as the first argument is less than, equal to, or
         * greater than the second.
         *
         * The implementor must ensure that
         * sgn( compare(x, y)) == -sgn(compare(y, x) ) for all x and y.
         * (This implies that compare(x, y) must throw an exception if and only
         * if compare(y, x) throws an exception.)
         *
         * The implementor must also ensure that the relation is transitive:
         * ((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0.
         *
         * Finally, the implementer must ensure that compare(x, y)==0 implies
         * that sgn(compare(x, z))==sgn(compare(y, z)) for all z.
         *
         * It is generally the case, but not strictly required that
         * (compare(x, y)==0) == ( x == y) ). Generally speaking, any comparator
         * that violates this condition should clearly indicate this fact. The
         * recommended language is "Note: this comparator imposes orderings that
         * are inconsistent with equals."
         * @param o1 - the first object to be compared
         * @param o2 - the second object to be compared
         * @returns a negative integer, zero, or a positive integer as the first
         * argument is less than, equal to, or greater than the second.
         */
        virtual int compare( const E& o1, const E& o2 ) = 0;

    };

}}

#endif /*_DECAF_UTIL_COMPARATOR_H_*/
