groovy.lang

## Annotation Type Delegate

-     @Documented
       @Retention(value=RUNTIME)
       @Target(value=FIELD)
      public @interface Delegate

  Field annotation to automatically delegate part of the functionality of an owner class to the annotated field.

  All public instance methods present in the type of the annotated field and not present in the owner class will be added to owner class at compile time. The implementation of such automatically added methods is code which calls through to the delegate as per the normal delegate pattern.

  As an example, consider this code:

       class Event {
           @Delegate Date when
           String title, url
       }

       def gr8conf = new Event(title: "GR8 Conference",
                                 url: "http://www.gr8conf.org",
                                when: Date.parse("yyyy/MM/dd", "2009/05/18"))

       def javaOne = new Event(title: "JavaOne",
                                 url: "http://java.sun.com/javaone/",
                                when: Date.parse("yyyy/MM/dd", "2009/06/02"))

       assert gr8conf.before(javaOne.when)

  In this example, the `Event` class will have a method called `before(Date otherDate)` as well as other public methods of the `Date` class. The implementation of the `before()` method will look like this:

           public boolean before(Date otherDate) {
               return when.before(otherDate);
           }

  By default, the owner class will also be modified to implement any interfaces implemented by the field. So, in the example above, because `Date` implements `Cloneable` the following will be true:

       assert gr8conf instanceof Cloneable

  This behavior can be disabled by setting the annotation's `interfaces` element to false, i.e. `@Delegate(interfaces = false)`, e.g. in the above example, the delegate definition would become:

            @Delegate(interfaces = false) Date when

  and the following would be true:

       assert !(gr8conf instanceof Cloneable)

  If multiple delegate fields are used and the same method signature occurs in more than one of the respective field types, then the delegate will be made to the first defined field having that signature. If this does occur, it might be regarded as a smell (or at least poor style) and it might be clearer to do the delegation by long hand.

  By default, methods of the delegate type marked as `@Deprecated` are not automatically added to the owner class (but see the technical note about interfaces below). You can force these methods to be added by setting the annotation's `deprecated` element to true, i.e. `@Delegate(deprecated = true)`.

  For example, in the example above if we change the delegate definition to:

            @Delegate(deprecated = true) Date when

  then the following additional lines will execute successfully (during 2009):

       assert gr8conf.year + 1900 == 2009
       assert gr8conf.toGMTString().contains(" 2009 ")

  Otherwise these lines produce a groovy.lang.MissingPropertyException or groovy.lang.MissingMethodException respectively as those two methods are `@Deprecated` in `Date`.

  Technical notes:

  - Static methods, synthetic methods or methods from the `GroovyObject` interface are not candidates for delegation
  - Non-abstract non-static methods defined in the owner class or its superclasses take precedence over methods with identical signatures from a `@Delegate` field
  - All methods defined in the owner class (including static, abstract or private etc.) take precedence over methods with identical signatures from a `@Delegate` field
  - Recursive delegation to your own class is not allowed
  - Mixing of `@Delegate` with default method arguments is known not to work in some cases. We recommend not using these features together.
  - When the type of the delegate field is an interface, the `deprecated` attribute will be ignored if the owner class implements that interface (i.e. you must set `interfaces=false` if you want the `deprecated` attribute to be used). Otherwise, the resulting class would not compile anyway without manually adding in any deprecated methods in the interface.
  Author:
    Alex Tkachman, Paul King

- - ### Optional Element Summary

    Optional Elements
    Modifier and Type | Optional Element and Description
    --- | ---
    `boolean` | `deprecated` Whether to apply the delegate pattern to deprecated methods; to avoid compilation errors, this is ignored if the type of the delegate field is an interface and `interfaces=true`.
    `java.lang.String[]` | `excludes` List of method and/or property names to exclude when delegating.
    `java.lang.Class[]` | `excludeTypes` List of interfaces containing method signatures to exclude when delegating.
    `java.lang.String[]` | `includes` List of method and/or property names to include when delegating.
    `java.lang.Class[]` | `includeTypes` List of interfaces containing method signatures to exclude when delegating.
    `boolean` | `interfaces`
    `boolean` | `methodAnnotations` Whether to carry over annotations from the methods of the delegate to your delegating method.
    `boolean` | `parameterAnnotations` Whether to carry over annotations from the parameters of delegate methods to your delegating method.

- - ### Element Detail

    - #### interfaces

          public abstract boolean interfaces

      Returns:
        true if owner class should implement interfaces implemented by field
      Default:
        true

  - - #### deprecated

          public abstract boolean deprecated

      Whether to apply the delegate pattern to deprecated methods; to avoid compilation errors, this is ignored if the type of the delegate field is an interface and `interfaces=true`.
      Returns:
        true if owner class should delegate to methods annotated with @Deprecated
      Default:
        false

  - - #### methodAnnotations

          public abstract boolean methodAnnotations

      Whether to carry over annotations from the methods of the delegate to your delegating method. Currently Closure annotation members are not supported.
      Returns:
        true if generated delegate methods should keep method annotations
      Default:
        false

  - - #### parameterAnnotations

          public abstract boolean parameterAnnotations

      Whether to carry over annotations from the parameters of delegate methods to your delegating method. Currently Closure annotation members are not supported.
      Returns:
        true if generated delegate methods should keep parameter annotations
      Default:
        false

  - - #### excludes

          public abstract java.lang.String[] excludes

      List of method and/or property names to exclude when delegating. Must not be used if 'includes' is used. For convenience, a String with comma separated names can be used in addition to an array (using Groovy's literal list notation) of String values. If interfaces is true (the default), you will need to manually supply any methods excluded from delegation that are required for the interface.
      Since:
        2.2.0
      Default:
        {}

  - - #### excludeTypes

          public abstract java.lang.Class[] excludeTypes

      List of interfaces containing method signatures to exclude when delegating. Only one of 'includes', 'includeTypes', 'excludes', 'excludeTypes' should be used. If interfaces is true (the default), you will need to manually supply any methods excluded from delegation that are required for the interface.
      Since:
        2.3.0
      Default:
        {}

  - - #### includes

          public abstract java.lang.String[] includes

      List of method and/or property names to include when delegating. Must not be used if 'excludes' is used. For convenience, a String with comma separated names can be used in addition to an array (using Groovy's literal list notation) of String values. If interfaces is true (the default), you will need to manually supply any methods not included via delegation that are required for the interface.
      Since:
        2.2.0
      Default:
        {}

  - - #### includeTypes

          public abstract java.lang.Class[] includeTypes

      List of interfaces containing method signatures to exclude when delegating. Only one of 'includes', 'includeTypes', 'excludes', 'excludeTypes' should be used. If interfaces is true (the default), you will need to manually supply any methods excluded from delegation that are required for the interface.
      Since:
        2.3.0
      Default:
        {}