Annotation Interface LinkTo


@Target({FIELD,TYPE}) @Retention(RUNTIME) @WriteAccess(LIFECYCLE) @MutuallyExclusive({"provider","providerType"}) @MutuallyExclusive({"field","fieldId","selector"}) @Inherited @Documented public @interface LinkTo
Provides mechanisms to automatically fill a field with an existing object from somewhere else in the model tree.

Example

Consider an environment model where you define different, interdependent services. Service 'provider' defines multiple users for various tasks, one being the one used by consumer. So we want the consumer object to use the same User object as the provider. This might look like this:

 @DSL abstract class Service {
   @Owner Environment env
 }

 @DSL class Producer extends Service {
   User admin
   User internal
   User monitoring
 }

 @DSL class Consumer extends Service {
   @LinkTo(provider={env.services.consumer}) User internal
 }
 
The LinkTo annotation on the internal field of the Consumer class will cause the internal field to be filled with the same User object as the internal field of the Producer class.

Usage

LinkTo is handled in the AutoLink phase, i.e. after owners have been set and auto-create objects have been created. It will work on any annotated field that is not yet set.

provider

The link mechanism is centered around the provider object, i.e. the object that contains the field to be linked. This is determined the following way:
  • provider: contains a code closure that is run relative to the annotated field's instance to access the owner (like in the example)
  • providerType: contains a type of owner. Finds the first element of the given type in the owner hierarchy
  • otherwise, the single owner field of the annotated field's class is used
If the annotated field's instance has no owner or multiple owner fields, the provider must be specified explicitly using the provider member. If the provider evaluates to null, the link is not set (no exception is thrown).

Map provider

If the provider is a map, the field name is used as the key to access the provider. If the key does not exist, the link is not set.

Target field

Once the provider is determined, the field of the provider to be used as the provider of the link is resolved. This is done the following way:
  • If the field member is set, the field with the given name is used
  • if the fieldId member is set, the field with the matching LinkSource annotation is taken
  • if the selector member is set, the field of the provider is determined by the value of the selector field of the annotated field's instance
  • It is illegal to have more than one of field, fieldId and selector set together
  • if neither field, fieldId nor selector is set, the field with the same name as the annotated field is used
  • if no field with the given name exists and exactly one field not annotated with LinkSource and of the correct type exists, that one is used
  • if no matching field is found, an exception is thrown
  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static enum 
     
  • Optional Element Summary

    Optional Elements
    Modifier and Type
    Optional Element
    Description
    The field of the target owner object to be used as the target for the link.
    If set use the field of the owner with a matching LinkSource annotation with the same id.
    If set, is added to automatically determined names (i.e.
    Class<? extends groovy.lang.Closure<Object>>
    The owner of the link.
    If set, the owner is determined by walking the owner hierarchy up until the given type is found.
    If set, the field of the provider is determined by the given selector.
    If set, determines the strategy to determine which field of the provider is to be used as the link source.
  • Element Details

    • field

      String field
      The field of the target owner object to be used as the target for the link.
      Default:
      ""
    • fieldId

      String fieldId
      If set use the field of the owner with a matching LinkSource annotation with the same id. Only one of field and targetId can be used at most.
      Default:
      ""
    • selector

      String selector
      If set, the field of the provider is determined by the given selector. The selector is the name of a field of the receiver. If the selector field is empty or null, the link is not set.
      Default:
      ""
    • provider

      Class<? extends groovy.lang.Closure<Object>> provider
      The owner of the link. By default, the owner of the annotated field's instance is used.
      Default:
      com.blackbuild.klum.ast.NoClosure.class
    • providerType

      Class<?> providerType
      If set, the owner is determined by walking the owner hierarchy up until the given type is found.
      Default:
      java.lang.Object.class
    • strategy

      LinkTo.Strategy strategy
      If set, determines the strategy to determine which field of the provider is to be used as the link source. FIELD_NAME: use the field with the same name as the annotated field, i.e. if the annotated field is called 'admin', the field 'admin' of the provider is used. OWNER_PATH: use the field with the same name as the instance name of the annotated field's owner, i.e. the name of the field of the annotated field's classes owner pointing to the instance of the annotated field's container. Can only be set together with one of provider or providerType.
      Default:
      AUTO
    • nameSuffix

      String nameSuffix
      If set, is added to automatically determined names (i.e. FIELD_NAME or OWNER_PATH).
      Default:
      ""