001package arez.annotations;
002
003import arez.component.ComponentObservable;
004import java.lang.annotation.Documented;
005import java.lang.annotation.ElementType;
006import java.lang.annotation.Target;
007
008/**
009 * Methods and fields annotated by this annotation should be observed for the alive lifetime of the component.
010 *
011 * <p>This annotation is typically used when a field references an {@link ArezComponent} annotated class that has
012 * {@link ArezComponent#disposeOnDeactivate()} set to <code>true</code>. This results in the current component
013 * observing the referenced component and thus preventing it from being disposed for the lifetime of the
014 * current component.</p>
015 *
016 * <p>It should be noted that it is preferable for the field that defines the observed component to be marked
017 * with this annotation rather than the method accessor. The reason is that the annotation processor will issue
018 * a warning if a field that the processor identifies as a potential dependency if it is not annotated with
019 * {@link AutoObserve}, {@link CascadeDispose} or {@link ComponentDependency}.</p>
020 *
021 * <p>If the element annotated is a method then the method must comply with the additional constraints:</p>
022 * <ul>
023 * <li>Must not be annotated with any other arez annotation other than {@link Reference} or {@link Observable}</li>
024 * <li>Must have 0 parameters</li>
025 * <li>Must return a value compatible with {@link ComponentObservable}, unless
026 *     {@link #validateTypeAtRuntime()} is <code>true</code></li>
027 * <li>Must not be private</li>
028 * <li>Must not be static</li>
029 * <li>Must not be abstract unless the method is annotated with {@link Reference} or {@link Observable} in which
030 *     case it MUST be abstract</li>
031 * <li>Must not throw exceptions</li>
032 * <li>Must be accessible to the class annotated by the {@link ArezComponent} annotation.</li>
033 * </ul>
034 *
035 * <p>If the element annotated is a field then the field must comply with the additional constraints:</p>
036 * <ul>
037 * <li>Must be final</li>
038 * <li>Must not be private</li>
039 * <li>Must not be static</li>
040 * <li>Must be compatible with {@link ComponentObservable}, unless {@link #validateTypeAtRuntime()} is
041 *     <code>true</code></li>
042 * <li>Must be accessible to the class annotated by the {@link ArezComponent} annotation.</li>
043 * <li>Should not be public. A warning will be generated but can be suppressed by the {@link SuppressWarnings} or {@link SuppressArezWarnings} annotations with a key "Arez:PublicField".</li>
044 * <li>
045 *   Should not be protected if in the class annotated with the {@link ArezComponent} annotation as the field is not
046 *   expected to be accessed outside the component. A warning will be generated but can be suppressed by the
047 *   {@link SuppressWarnings} or {@link SuppressArezWarnings} annotations with a key "Arez:ProtectedField".
048 * </li>
049 * </ul>
050 *
051 * <p>If {@link #validateTypeAtRuntime()} is set to <code>true</code> then the declared type of the field or method
052 * must be annotated with {@link ArezComponentLike}. In this mode, type compatibility is validated at runtime
053 * rather than compile time while still treating the declared type as component-like for validation only.</p>
054 *
055 * <p>This annotation is only supported on elements contained within a type annotated by
056 * {@link ArezComponent} or {@link ArezComponentLike}. Other usages will fail compilation.</p>
057 */
058@Documented
059@Target( { ElementType.METHOD, ElementType.FIELD } )
060public @interface AutoObserve
061{
062  /**
063   * Return true and the value of the annotated field or method will be validated at runtime rather than compile time.
064   * This is useful when the declared type is annotated with {@link ArezComponentLike} but the runtime value is
065   * known to implement {@link ComponentObservable}.
066   *
067   * @return true to defer validation of types until runtime.
068   */
069  boolean validateTypeAtRuntime() default false;
070}