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