001package react4j.annotations;
002
003import arez.annotations.AutoObserve;
004import arez.annotations.ComponentDependency;
005import arez.annotations.Memoize;
006import arez.annotations.Observable;
007import arez.annotations.Observe;
008import java.lang.annotation.Documented;
009import java.lang.annotation.ElementType;
010import java.lang.annotation.Target;
011import javax.annotation.Nonnull;
012
013/**
014 * Annotation used to specify an input.
015 * The property is extracted from Reacts underlying props object. By default the input is passed as a
016 * value in when creating the view but it can also be retrieved from the react context.
017 * When applied to an abstract method, the input is mutable.
018 * When applied to a constructor parameter, the input is immutable.
019 *
020 * <p>If applied to a method, the method that is annotated with this annotation must also comply with the
021 * following constraints:</p>
022 * <ul>
023 * <li>Must not be annotated with any other react annotation</li>
024 * <li>Must have 0 parameters</li>
025 * <li>Must return a value</li>
026 * <li>Must be an abstract instance method</li>
027 * <li>Must not throw exceptions</li>
028 * <li>Must be accessible from the same package as the class annotated by {@link View}</li>
029 * <li>
030 *   Should not be public as not expected to be invoked outside the view. A warning will be generated but can
031 *   be suppressed by the {@link SuppressWarnings} or {@link SuppressReact4jWarnings} annotations with a key
032 *   "React4j:PublicMethod". This warning is also suppressed by the annotation processor if it is implementing
033 *   an interface method.
034 * </li>
035 * <li>
036 *   Should not be protected if in the class annotated with the {@link View} annotation as the method is not
037 *   expected to be invoked outside the view. A warning will be generated but can be suppressed by the
038 *   {@link SuppressWarnings} or {@link SuppressReact4jWarnings} annotations with a key "React4j:ProtectedMethod".
039 * </li>
040 * <li>
041 *   Should be annotated with either {@link javax.annotation.Nonnull} or {@link javax.annotation.Nullable} if the
042 *   return type is not a primitive. A warning will be generated but can be suppressed by the {@link SuppressWarnings}
043 *   or {@link SuppressReact4jWarnings} annotations with a key "React4j:MissingInputNullability".
044 * </li>
045 * </ul>
046 */
047@Documented
048@Target( { ElementType.METHOD, ElementType.PARAMETER } )
049public @interface Input
050{
051  /**
052   * Return the name of the input.
053   * The name is the key used when accessing the input from the inputs object. It is also used when creating
054   * the builder steps associated with the inputs that set {@link #source()} to {@link Source#DEFAULT}.
055   *
056   * @return the name of the input.
057   */
058  @Nonnull
059  String name() default "<default>";
060
061  /**
062   * Return the qualifier used to access value from context.
063   * It must only be specified if {@link #source()} is set to {@link Source#CONTEXT}.
064   *
065   * @return the qualifier used to access value from context.
066   */
067  @Nonnull
068  String qualifier() default "";
069
070  /**
071   * The setting controlling where the input value is source from.
072   * If the source is set to {@link Source#CONTEXT} then the input is sometimes described as a "TreeInput"
073   * as it is transparently passed from a parent view to all child views. A "TreeInput" does not
074   * have to be specified by the user when creating the view.
075   *
076   * @return the setting controlling where the input value is source from.
077   */
078  Source source() default Source.DEFAULT;
079
080  /**
081   * Setting indicating whether the input should be supplied when the view is constructed.
082   * This influences validation when enabled and how the Builder class is created.
083   * If set to {@link Feature#ENABLE} then the user MUST supply the input and the builder will require the user
084   * to specify the value. If set to {@link Feature#DISABLE} then the user can optionally supply the input.
085   * If set to {@link Feature#AUTODETECT} then the annotation processor will treat it as {@link Feature#DISABLE}
086   * if there is a corresponding {@link InputDefault} for the input or the {@link #source()} parameter is set to
087   * {@link Source#CONTEXT}, otherwise it will be treated as {@link Feature#ENABLE}. The value of this setting
088   * must not be {@link Feature#ENABLE} when {@link #source()} is set to {@link Source#CONTEXT}.
089   *
090   * @return the flag indicating whether the input needs to be supplied.
091   */
092  Feature require() default Feature.AUTODETECT;
093
094  /**
095   * Indicate whether the input should be annotated by {@link Observable}.
096   *
097   * <p>If set to {@link Feature#AUTODETECT} then the input will be observable if and only if:</p>
098   * <ul>
099   * <li>the input is not immutable.</li>
100   * <li>the view has at least one method annotated with {@link Memoize} or {@link Observe}.</li>
101   * </ul>
102   *
103   * @return the enum indicating whether input is observable.
104   */
105  Feature observable() default Feature.AUTODETECT;
106
107  /**
108   * Enum where the input is sourced from.
109   */
110  enum Source
111  {
112    /**
113     * The input value is passed to the view during construction.
114     */
115    DEFAULT,
116    /**
117     * The input value is retrieved from the react context.
118     */
119    CONTEXT
120  }
121}