Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2024 Stephan Pauxberger
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.blackbuild.klum.ast.util.layer3.annotations;
import com.blackbuild.groovy.configdsl.transform.NamedAnnotationMemberClosure;
import com.blackbuild.groovy.configdsl.transform.WriteAccess;
import com.blackbuild.groovy.configdsl.transform.cast.NeedsDSLClass;
import com.blackbuild.klum.cast.KlumCastValidated;
import com.blackbuild.klum.cast.checks.AlsoNeeds;
import com.blackbuild.klum.cast.checks.MutuallyExclusive;
import groovy.lang.Closure;
import java.lang.annotation.*;
/**
* 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:
*
*
* {@literal @}DSL abstract class Service {
* {@literal @}Owner Environment env
* }
*
* {@literal @}DSL class Producer extends Service {
* User admin
* User internal
* User monitoring
* }
*
* {@literal @}DSL class Consumer extends Service {
* {@literal @}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. It is illegal
* to have field and fieldId set together
*
if neither field nor fieldId 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
*
*/
@Target({ElementType.FIELD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@WriteAccess(WriteAccess.Type.LIFECYCLE)
@KlumCastValidated
@NeedsDSLClass
@MutuallyExclusive({"provider", "providerType"})
@Inherited
@Documented
public @interface LinkTo {
/**
* The field of the target owner object to be used as the target for the link.
*/
String field() default "";
/**
* 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.
*/
String fieldId() default "";
/**
* The owner of the link. By default, the owner of the annotated field's instance is used.
*/
Class extends Closure