001package arez.annotations; 002 003import arez.ComputableValue; 004import arez.Observer; 005import java.lang.annotation.Documented; 006import java.lang.annotation.ElementType; 007import java.lang.annotation.Target; 008import javax.annotation.Nonnull; 009 010/** 011 * Annotation that marks a method as observed. 012 * Any {@link arez.ObservableValue} instances or {@link ComputableValue} instances accessed within the 013 * scope of the method will be added as a dependency of the observer. If any of these dependencies are changed 014 * then the runtime will invoke the associated {@link OnDepsChange} method if present or re-schedule the observed 015 * method for execution if there is no {@link OnDepsChange} method present. Note that Arez will attempt to detect 016 * the {@link OnDepsChange} method using naming conventions even if there is no method explicitly annotated. 017 * 018 * <p>The method that is annotated with this annotation must comply with the additional constraints:</p> 019 * <ul> 020 * <li>Must not be annotated with any other arez annotation</li> 021 * <li>Must not be private</li> 022 * <li>Must not be static</li> 023 * <li>Must not be final</li> 024 * <li>Must not be abstract</li> 025 * </ul> 026 * 027 * <p>If the {@link #executor()} is set to {@link Executor#INTERNAL} then the method must also 028 * comply with the following additional constraints:</p> 029 * <ul> 030 * <li>Must not be public</li> 031 * <li>Must have 0 parameters</li> 032 * <li>Must not return a value</li> 033 * <li>Must not throw exceptions</li> 034 * <li>Must be accessible to the class annotated by the {@link ArezComponent} annotation.</li> 035 * </ul> 036 * 037 * <p>This annotation is only supported on elements contained within a type annotated by 038 * {@link ArezComponent} or {@link ArezComponentLike}. Other usages will fail compilation.</p> 039 */ 040@Documented 041@Target( ElementType.METHOD ) 042public @interface Observe 043{ 044 /** 045 * Return the name of the Observer relative to the component. 046 * The value must conform to the requirements of a java identifier. 047 * The name must also be unique across {@link Observable}s, 048 * {@link Memoize}s and {@link Action}s within the scope of the 049 * {@link ArezComponent} annotated element. 050 * 051 * @return the name of the Observer relative to the component. 052 */ 053 @Nonnull 054 String name() default "<default>"; 055 056 /** 057 * Does the observer's tracking method change arez state or not. 058 * Observers are primarily used to reflect Arez state onto external systems (i.e. views, network layers etc.) 059 * and thus the default value is false thus making the transaction mode read-only. 060 * 061 * @return true if the observer should use a read-write transaction, false if it should use a read-only transaction. 062 */ 063 boolean mutation() default false; 064 065 /** 066 * The priority of the underlying observer 067 * 068 * @return the priority of the observer. 069 */ 070 Priority priority() default Priority.DEFAULT; 071 072 /** 073 * The actor responsible for calling the observed method. 074 * 075 * @return the actor responsible for calling the observed method. 076 */ 077 Executor executor() default Executor.INTERNAL; 078 079 /** 080 * Flag controlling whether the observer can observe ComputableValue instances with lower priorities. 081 * The default value of false will result in an invariant failure (in development mode) if a lower priority 082 * dependency is observed by the observer. This is to prevent priority inversion when scheduling a higher 083 * priority observer that is dependent upon a lower priority computable value. If the value is true then the no 084 * invariant failure is triggered and the component relies on the component author to handle possible priority 085 * inversion. 086 * 087 * @return false if observing lower priority dependencies should result in invariant failure in development mode. 088 */ 089 boolean observeLowerPriorityDependencies() default false; 090 091 /** 092 * Can the observer invoke actions. 093 * An action that specifies {@link Action#requireNewTransaction()} as true will start a new transaction 094 * and any observables accessed within the action will not be dependencies of the observer. Sometimes this 095 * behaviour is desired. Sometimes an action that specifies {@link Action#requireNewTransaction()} as false 096 * will be used instead and any observable accessed within the scope of the action will be a dependency of 097 * the observer and thus changes in the observable will reschedule the observer. Sometimes this 098 * behaviour is desired. Either way the developer must be conscious of these decisions and thus must explicitly 099 * set this flag to true to invoke any actions within the scope of the observers reaction. 100 * 101 * @return true if the observer can invoke actions, false otherwise. 102 */ 103 boolean nestedActionsAllowed() default false; 104 105 /** 106 * Return true if the parameters should be reported to the core Arez runtime. 107 * It is useful to disable reporting for large, circular or just uninteresting parameters to the spy infrastructure. 108 * 109 * @return true to report the parameters, false otherwise. 110 */ 111 boolean reportParameters() default true; 112 113 /** 114 * Return true if the return value of the observed function (if any) should be reported to the Arez spy subsystem. 115 * It is useful to disable reporting for large, circular or just uninteresting parameters to the spy infrastructure. 116 * This is only useful if the value of {@link #executor()} is set to {@link Executor#EXTERNAL} as otherwise the 117 * result is not reported anyway. 118 * 119 * @return true to report the return value, false otherwise. 120 */ 121 boolean reportResult() default true; 122 123 /** 124 * Enum indicating whether the Observer is derived from arez elements and/or external dependencies. 125 * If set to {@link DepType#AREZ} then the arez runtime will verify that the method annotated by this 126 * annotation accesses arez elements (i.e. instances of {@link arez.ObservableValue} or instances of 127 * {@link ComputableValue}). If set to {@link DepType#AREZ_OR_NONE} then the runtime will allow 128 * observed to exist with no dependencies. If set to {@link DepType#AREZ_OR_EXTERNAL} then the component 129 * must define a {@link ObserverRef} method and should invoke {@link Observer#reportStale()} when the 130 * non-arez dependencies are changed. 131 * 132 * @return the type of dependencies allowed in the observed method. 133 */ 134 @Nonnull 135 DepType depType() default DepType.AREZ; 136}