Package groovy.transform

# Annotation Type Sortable

    @Retention(RUNTIME)
    @Target(TYPE)
    public @interface Sortable

A class annotation used to make a class Comparable by (potentially) 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 | Description
  --- | --- | ---
  `boolean` | `allNames` | Whether to include all fields and/or properties in the comparison algorithm, including those with names that are considered internal.
  `boolean` | `allProperties` | Whether to include all properties (as per the JavaBean spec) in the comparison algorithm.
  `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` | `includeSuperProperties` | Whether to include super properties in the comparison algorithm.
  `boolean` | `reversed` | Set to true so that comparator uses reversed natural order.

- ## Element Details

  - ### includes

    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

    java.lang.String[] excludes
    Property names to exclude in the comparison algorithm. Must not be used if 'includes' is used.
    Default:
      {}

  - ### reversed

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

  - ### includeSuperProperties

    boolean includeSuperProperties
    Whether to include super properties in the comparison algorithm. Groovy properties and potentially JavaBean properties (in that order) from superclasses come before the members from a subclass (unless 'includes' is used to determine the order).
    Since:
      2.5.2
    Default:
      false

  - ### allProperties

    boolean allProperties
    Whether to include all properties (as per the JavaBean spec) in the comparison algorithm. Groovy recognizes any field-like definitions with no explicit visibility as property definitions and always includes them in the comparison algorithm. Groovy also treats any explicitly created getXxx() or isYyy() methods as property getters as per the JavaBean specification. Set this flag to false explicitly exclude such properties. JavaBean properties come after any Groovy properties for a given class (unless 'includes' is used to determine the order).
    Since:
      2.5.2
    Default:
      true

  - ### allNames

    boolean allNames
    Whether to include all fields and/or properties in the comparison algorithm, including those with names that are considered internal.
    Since:
      2.5.2
    Default:
      false