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 * <p>This annotation is only supported on elements contained within a type annotated by
030 * {@link ArezComponent} or {@link ArezComponentLike}. Other usages will fail compilation.</p>
031 */
032@Documented
033@Target( ElementType.METHOD )
034public @interface Reference
035{
036  /**
037   * Return the name of the reference relative to the component. The value must conform
038   * to the requirements of a java identifier. If not specified, the name will be derived by assuming
039   * the naming convention "get[Name]" or failing that the name will be the method name.
040   *
041   * @return the name of the reference relative to the component.
042   */
043  @Nonnull
044  String name() default "<default>";
045
046  /**
047   * Return the strategy for resolving reference.
048   *
049   * @return the strategy for resolving reference.
050   */
051  @Nonnull
052  LinkType load() default LinkType.EAGER;
053
054  /**
055   * Return the enum controlling whether there is an inverse for reference.
056   * {@link Feature#ENABLE} tells the annotation processor to expect an inverse and add code
057   * to maintain the inverse. {@link Feature#DISABLE} will generate no code to maintain
058   * inverse module. {@link Feature#AUTODETECT} will be treated as {@link Feature#ENABLE}
059   * if either the {@link #inverseName} or {@link #inverseMultiplicity} is specified.
060   *
061   * @return the enum controlling whether there is an inverse for reference
062   */
063  @Nonnull
064  Feature inverse() default Feature.AUTODETECT;
065
066  /**
067   * Return the name of the inverse associated with the reference. The value must conform
068   * to the requirements of a java identifier. If not specified, the name will be derived
069   * by camelCasing the simple name of the class on which the {@link Reference} annotation
070   * is placed and then adding an s if {@link #inverseMultiplicity} is {@link Multiplicity#MANY}.
071   *
072   * @return the name of the reference relative to the component.
073   */
074  @Nonnull
075  String inverseName() default "<default>";
076
077  /**
078   * Define the expected multiplicity of the inverse associated with the reference.
079   *
080   * @return the expected multiplicity of the inverse associated with the reference.
081   */
082  @Nonnull
083  Multiplicity inverseMultiplicity() default Multiplicity.MANY;
084}