/*
 * [TestReverse.java]
 *
 * Summary: Demonstrate use of reverseOrder with Comparables and Comparators.
 *
 * Copyright: (c) 2007-2017 Roedy Green, Canadian Mind Products, http://mindprod.com
 *
 * Licence: This software may be copied and used freely for any purpose but military.
 *          http://mindprod.com/contact/nonmil.html
 *
 * Requires: JDK 1.8+
 *
 * Created with: JetBrains IntelliJ IDEA IDE http://www.jetbrains.com/idea/
 *
 * Version History:
 *  1.0 2009-05-23 initial version
 */
package com.mindprod.example;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

import static java.lang.System.*;

/**
 * Demonstrate use of reverseOrder with Comparables and Comparators.
 *
 * @author Roedy Green, Canadian Mind Products
 * @version 1.0 2009-05-23 developed from snippet
 * @since 2009-05-23
 */
public class TestReverse
    {
    /**
     * test harness
     *
     * @param args not used
     */
    public static void main( String[] args )
        {
        final ArrayList<Pair> listOfPairs = new ArrayList<>( 4 );
        listOfPairs.add( new Pair( "index.html", 1700000 ) );
        listOfPairs.add( new Pair( "unmain.html", 2500000 ) );
        listOfPairs.add( new Pair( "feedback.html", 10000 ) );
        listOfPairs.add( new Pair( "zip.html", 43449 ) );
        Collections.sort( listOfPairs,
                Collections.reverseOrder() ); // reverse alphabetically, the natural Comparable order.
        for ( Pair p : listOfPairs )
            {
            out.println( p.count + " " + p.filename );
            }
        // Note that reverseOrder is only for sorting Objects in reverse order.
        // Arrays.sort does not support Comparators or reverseOrder, except for Objects.
        // You can't sort an array of primitive int it reverse order.
        Collections.sort( listOfPairs, Collections.reverseOrder( new Numerically() ) );
        for ( Pair p : listOfPairs )
            {
            out.println( p.count + " " + p.filename );
            }
        }

    /**
     * Case insensitive ascending by filename.
     * <p/>
     * Defines an alternate sort order for Pair.
     */
    private static class Numerically implements Comparator<Pair>   // <-- <Pair>
        {
        /**
         * Case insensitive ascending by filename.
         * Defines an alternate sort order for Pair with JDK 1.5+ generics.
         * Compare two Pair Objects.
         * Compares count then filename.
         * Informally, returns (a-b), or +ve if a is more positive than b.
         *
         * @param a first Pair to compare
         * @param b second Pair to compare
         *
         * @return +ve if a&gt;b, 0 if a==b, -ve if a&lt;b
         */
        public final int compare( Pair a, Pair b )   // <-- Pair, not Object
            {
            int diff = a.count - b.count;   // <-- no cast
            if ( diff != 0 )
                {
                return diff;
                }
            return a.filename.compareToIgnoreCase( b.filename );
            }
        }

    /**
     * Class to represent an Filename/Count pair.
     */
    static class Pair implements Comparable<Pair>  // <---  note <Pair>
        {
        /**
         * The name of one file to be described.
         */
        final String filename;

        /**
         * hit count.
         */
        final int count;

        /**
         * Constructor.
         *
         * @param filename a filename
         * @param count    some number associated with the file.
         */
        Pair( String filename, int count )
            {
            this.filename = filename;
            this.count = count;
            }

        /**
         * Case insensitive ascending by filename.
         * Defines default the sort order for Pair Objects.
         * Compare this Pair with another Pair with JDK 1.5+ generics.
         * Compares filename.
         * Informally, returns (this-other) or +ve if this is more positive than other.
         *
         * @param other other Pair to compare with this one
         *
         * @return +ve if this&gt;other, 0 if this==other, -ve if this&lt;other
         */
        public final int compareTo( Pair other )   // <-- Pair, not Object
            {
            return this.filename.compareToIgnoreCase( other.filename );    // <-- no cast
            }
        } // end class Pair
    }