All Downloads are FREE. Search and download functionalities are using the official Maven repository.

groovy.lang.Delegate Maven / Gradle / Ivy

The newest version!
/*
 *  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.
 */
package groovy.lang;

import org.codehaus.groovy.transform.GroovyASTTransformationClass;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 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 {
 *     {@code @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 {@code Event} class will have a method called * {@code before(Date otherDate)} as well as other public methods of the * {@code Date} class. * The implementation of the {@code 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 {@code Date} * implements {@code Cloneable} the following will be true: * *
 * assert gr8conf instanceof Cloneable
 * 
* * This behavior can be disabled by setting the * annotation's {@code interfaces} element to false, * i.e. {@code @Delegate(interfaces = false)}, e.g. in the above * example, the delegate definition would become: *
 *     {@code @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 {@code @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 {@code deprecated} element to true, * i.e. {@code @Delegate(deprecated = true)}. *

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

 *     {@code @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 * {@code @Deprecated} in {@code 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 {@code @Delegate} field
  • *
  • All methods defined in the owner class (including static, abstract or private etc.) * take precedence over methods with identical signatures from a {@code @Delegate} field
  • *
  • Recursive delegation to your own class is not allowed
  • *
  • Mixing of {@code @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 {@code deprecated} attribute will be * ignored if the owner class implements that interface (i.e. you must set {@code interfaces=false} * if you want the {@code 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 * @author Paul King */ @java.lang.annotation.Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) @GroovyASTTransformationClass("org.codehaus.groovy.transform.DelegateASTTransformation") public @interface Delegate { /** * @return true if owner class should implement interfaces implemented by field */ boolean interfaces() default true; /** * 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 * {@code interfaces=true}. * * @return true if owner class should delegate to methods annotated with @Deprecated */ boolean deprecated() default false; /** * Whether to carry over annotations from the methods of the delegate * to your delegating method. Currently Closure annotation members are * not supported. * * @return true if generated delegate methods should keep method annotations */ boolean methodAnnotations() default false; /** * Whether to carry over annotations from the parameters of delegate * methods to your delegating method. Currently Closure annotation members are * not supported. * * @return true if generated delegate methods should keep parameter annotations */ boolean parameterAnnotations() default false; /** * 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 */ String[] excludes() default {}; /** * 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 */ Class[] excludeTypes() default {}; /** * 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 */ String[] includes() default {}; /** * 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 */ Class[] includeTypes() default {}; }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy