groovy.transform

## Annotation Type Sortable

-     @Retention(value=RUNTIME)
       @Target(value=TYPE)
      public @interface Sortable

  A class annotation used to make a class Comparable by multiple Comparators. As an example, given this class:

        @Sortable class Person {
           String first
           String last
           Integer born
       }

  The generated Groovy class will:
  - implement the `Comparable` interface
  - have a `compareTo` method based on the `first`, `last` and `born` properties (priority ordering will be according to the ordering of property definition, highest first, unless 'includes' is used; in which case, priority will be according to the order given in the includes list)
  - have three `Comparator` methods named `comparatorByFirst`, `comparatorByLast` and `comparatorByBorn`
  - sort by natural order by default, reversed natural order can be specified
  The properties within the class must themselves be `Comparable` or `@Sortable`.

  More examples:

       //--------------------------------------------------------------------------
       import groovy.transform.Sortable
       import groovy.transform.ToString

       @Sortable
       @ToString
       class Course {
           // Order of properties determines priority when sorting
           String title
           Date beginDate
           Integer maxAttendees  // int doesn't implement Comparable, so use Integer
       }

       final Course groovy = new Course(
               title: 'Groovy', beginDate: new Date() + 7, maxAttendees: 40)
       final Course groovy2 = new Course(
               title: 'Groovy', beginDate: new Date() + 2, maxAttendees: 50)
       final Course grails = new Course(
               title: 'Grails', beginDate: new Date() + 1, maxAttendees: 20)

       final List<Course> courses = [groovy, groovy2, grails]
       assert courses.last().title == 'Grails'

       // Use toSorted() method to sort
       final List<Course> sorted = courses.toSorted()

       assert sorted.first().title == 'Grails'
       assert sorted.last().title == 'Groovy'
       assert sorted.maxAttendees == [20, 50, 40]

       //--------------------------------------------------------------------------
       // Order of fields for includes determines priority when sorting
       import groovy.transform.Sortable
       import groovy.transform.ToString

       @Sortable(includes = ['title', 'maxAttendees'])
       // Or @Sortable(excludes = ['beginDate'])
       @ToString
       class Course {
           String title
           Date beginDate
           Integer maxAttendees
       }

       final Course groovy = new Course(
               title: 'Groovy', beginDate: new Date() + 7, maxAttendees: 40)
       final Course groovy2 = new Course(
               title: 'Groovy', beginDate: new Date() + 2, maxAttendees: 50)
       final Course grails = new Course(
               title: 'Grails', beginDate: new Date() + 1, maxAttendees: 20)

       final List<Course> courses = [groovy, groovy2, grails]

       // Use toSorted() method to sort
       final List<Course> sorted = courses.toSorted()

       assert sorted.first().title == 'Grails'
       assert sorted.last().title == 'Groovy'
       assert sorted.maxAttendees == [20, 40, 50]

       //--------------------------------------------------------------------------
       // Static methods to create comparators.
       final Comparator byMaxAttendees = Course.comparatorByMaxAttendees()
       final List<Course> sortedByMaxAttendees = courses.sort(false, byMaxAttendees)

       assert sortedByMaxAttendees.maxAttendees == [20, 40, 50]
       // beginDate is not used for sorting
       assert sortedByMaxAttendees[2].beginDate < sortedByMaxAttendees[1].beginDate

       assert Course.declaredMethods.name.findAll { it.startsWith('comparatorBy') }.toSorted() == ['comparatorByMaxAttendees', 'comparatorByTitle']

       //--------------------------------------------------------------------------
       // Sorting by max attendees using reversed order
       import groovy.transform.Sortable
       import groovy.transform.ToString

       @Sortable(includes = ['points'], reversed = true)
       @ToString
       class LeaderBoardEntry {
           String team
           int points
       }

       final LeaderBoardEntry teamA = new LeaderBoardEntry(team: "Team A", points: 30)
       final LeaderBoardEntry teamB = new LeaderBoardEntry(team: "Team B", points: 80)
       final LeaderBoardEntry teamC = new LeaderBoardEntry(team: "Team C", points: 50)

       final List<LeaderBoardEntry> leaderBoard = [teamA, teamB, teamC].toSorted()

       assert leaderBoard.first().team == 'Team B'
       assert leaderBoard.last().team == 'Team A'
       assert leaderBoard.points == [80, 50, 30]

- - ### Optional Element Summary

    Optional Elements
    Modifier and Type | Optional Element and Description
    --- | ---
    `java.lang.String[]` | `excludes` Property names to exclude in the comparison algorithm.
    `java.lang.String[]` | `includes` Property names to include in the comparison algorithm.
    `boolean` | `reversed` Set to true so that comparator uses reversed natural order.

- - ### Element Detail

    - #### includes

          public abstract java.lang.String[] includes

      Property names to include in the comparison algorithm. Must not be used if 'excludes' is used. The default value is a special marker value indicating that no includes are defined; all properties are included if 'includes' remains undefined and 'excludes' is explicitly or implicitly an empty list.
      Default:
        "<DummyUndefinedMarkerString-DoNotUse>"

  - - #### excludes

          public abstract java.lang.String[] excludes

      Property names to exclude in the comparison algorithm. Must not be used if 'includes' is used.
      Default:
        {}

  - - #### reversed

          public abstract boolean reversed

      Set to true so that comparator uses reversed natural order.
      Since:
        2.5.0
      Default:
        false