001package arez.annotations;
002
003import arez.Locator;
004import java.lang.annotation.Documented;
005import java.lang.annotation.ElementType;
006import java.lang.annotation.Target;
007import javax.annotation.Nonnull;
008
009/**
010 * A Reference annotation is placed on an abstract method that will resolve to a referenced object.
011 * The reference annotation is paired with a {@link ReferenceId} method that returns the <code>id</code>
012 * of the referenced object. The <code>type</code> of the referenced object is the return type of the method
013 * annotated with <code>@Reference</code>. The <code>type</code> and <code>id</code> are passed to the
014 * {@link Locator#findById(Class, Object)} method when the reference is resolved.
015 *
016 * * <p>The reference can be resolved either eagerly (during a linking phase or when it is modified) or
017 * lazily (when accessed).</p>
018 *
019 * <p>The method must also conform to the following constraints:</p>
020 * <ul>
021 * <li>Must not be annotated with any other arez annotation</li>
022 * <li>Must have 0 parameters</li>
023 * <li>Must return a value</li>
024 * <li>Must be abstract</li>
025 * <li>Must not throw exceptions</li>
026 * <li>Must be accessible to the class annotated by the {@link ArezComponent} annotation.</li>
027 * </ul>
028 */
029@Documented
030@Target( ElementType.METHOD )
031public @interface Reference
032{
033  /**
034   * Return the name of the reference relative to the component. The value must conform
035   * to the requirements of a java identifier. If not specified, the name will be derived by assuming
036   * the naming convention "get[Name]" or failing that the name will be the method name.
037   *
038   * @return the name of the reference relative to the component.
039   */
040  @Nonnull
041  String name() default "<default>";
042
043  /**
044   * Return the strategy for resolving reference.
045   *
046   * @return the strategy for resolving reference.
047   */
048  @Nonnull
049  LinkType load() default LinkType.EAGER;
050
051  /**
052   * Return the enum controlling whether there is an inverse for reference.
053   * {@link Feature#ENABLE} tells the annotation processor to expect an inverse and add code
054   * to maintain the inverse. {@link Feature#DISABLE} will generate no code to maintain
055   * inverse module. {@link Feature#AUTODETECT} will be treated as {@link Feature#ENABLE}
056   * if either the {@link #inverseName} or {@link #inverseMultiplicity} is specified.
057   *
058   * @return the enum controlling whether there is an inverse for reference
059   */
060  @Nonnull
061  Feature inverse() default Feature.AUTODETECT;
062
063  /**
064   * Return the name of the inverse associated with the reference. The value must conform
065   * to the requirements of a java identifier. If not specified, the name will be derived
066   * by camelCasing the simple name of the class on which the {@link Reference} annotation
067   * is placed and then adding an s if {@link #inverseMultiplicity} is {@link Multiplicity#MANY}.
068   *
069   * @return the name of the reference relative to the component.
070   */
071  @Nonnull
072  String inverseName() default "<default>";
073
074  /**
075   * Define the expected multiplicity of the inverse associated with the reference.
076   *
077   * @return the expected multiplicity of the inverse associated with the reference.
078   */
079  @Nonnull
080  Multiplicity inverseMultiplicity() default Multiplicity.MANY;
081}