001package arez.annotations; 002 003import arez.component.DisposeNotifier; 004import java.lang.annotation.Documented; 005import java.lang.annotation.ElementType; 006import java.lang.annotation.Target; 007import javax.annotation.Nonnull; 008 009/** 010 * Methods and fields marked with this annotation are dependencies of the component. 011 * If the dependency is disposed then the component takes an action to cascade the dispose 012 * or null the property referencing the dependency. The dependency MUST implement the 013 * {@link DisposeNotifier} interface. 014 * 015 * <p>It should be noted that it is preferable for the field that defines the dependency is marked 016 * with this annotation rather than the method accessor. The reason is that the annotation processor 017 * will issue a warning if a field that the processor identifies as a potential dependency if it is 018 * not annotated with {@link ComponentDependency} or {@link CascadeDispose}.</p> 019 * 020 * <p>If the element annotated is a method then the method must comply with the additional constraints:</p> 021 * <ul> 022 * <li>Must not be annotated with any other arez annotation except {@link Observable}</li> 023 * <li>If not annotated with {@link Observable} then must be final</li> 024 * <li>Must have 0 parameters</li> 025 * <li> 026 * Must return a value that implements {@link DisposeNotifier} or is annotated with {@link ArezComponent}. 027 * This will be checked at compile-time unless {@link #validateTypeAtRuntime()} set to <code>true</code>. 028 * </li> 029 * <li>Must not be private</li> 030 * <li>Must not be static</li> 031 * <li>If not annotated with {@link Observable} then must not be abstract</li> 032 * <li>Must not throw exceptions</li> 033 * <li>Must be accessible to the class annotated by the {@link ArezComponent} annotation.</li> 034 * </ul> 035 * 036 * <p>If the element annotated is a field then the field must comply with the additional constraints:</p> 037 * <ul> 038 * <li>Must be final</li> 039 * <li>Must be a type that implements {@link DisposeNotifier} or is annotated with {@link ArezComponent}</li> 040 * <li>Must not be private</li> 041 * <li>Must not be static</li> 042 * <li>Must be accessible to the class annotated by the {@link ArezComponent} annotation.</li> 043 * </ul> 044 */ 045@Documented 046@Target( { ElementType.METHOD, ElementType.FIELD } ) 047public @interface ComponentDependency 048{ 049 /** 050 * The action to take when dependency is disposed. 051 */ 052 enum Action 053 { 054 /** 055 * Remove the component. 056 */ 057 CASCADE, 058 /** 059 * Set the {@link Observable} property that holds dependency to null. 060 */ 061 SET_NULL 062 } 063 064 /** 065 * Return the action to take when the dependency is disposed. 066 * A {@link Action#CASCADE} value indicates that the component should be deleted, while a 067 * {@link Action#SET_NULL} value indicates that the observable field should be set to null. 068 * The {@link Action#SET_NULL} is only valid on {@link Observable} properties that have an 069 * associated setter and are not annotated with {@link javax.annotation.Nonnull}. 070 * 071 * @return the action to take when the dependency is disposed. 072 */ 073 @Nonnull 074 Action action() default Action.CASCADE; 075 076 /** 077 * Return true and the value of the annotated field will be validated at runtime rather than at compile time. 078 * This is useful when the field is defined by an interface but the underlying field is guaranteed to implement 079 * {@link DisposeNotifier} at runtime. 080 * 081 * @return true to defer validation of types until runtime. 082 */ 083 boolean validateTypeAtRuntime() default false; 084}