/** * Copyright (c) 2017-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ package com.facebook.litho.specmodels.model; import javax.annotation.concurrent.Immutable; import javax.lang.model.element.Modifier; import java.lang.annotation.Annotation; import com.facebook.litho.specmodels.internal.ImmutableList; import com.squareup.javapoet.AnnotationSpec; import com.squareup.javapoet.MethodSpec; import com.squareup.javapoet.TypeName; /** * Describes the signature and other feature of a delegate method. * * We use method descriptions to refer to abstract methods defined in * com.facebook.litho.ComponentLifecycle, so that we can define implementations that delegate * to client-declared methods with annotated props. */ @Immutable public final class DelegateMethodDescription { /** * Defines possible param types that can be used in delegate methods. */ public enum OptionalParameterType { PROP, TREE_PROP, STATE, PARAM, INTER_STAGE_OUTPUT, PROP_OUTPUT, STATE_OUTPUT, STATE_VALUE, } public final ImmutableList<AnnotationSpec> annotations; public final Modifier accessType; public final TypeName returnType; public final String name; public final ImmutableList<TypeName> definedParameterTypes; public final ImmutableList<OptionalParameterType> optionalParameterTypes; public final ImmutableList<Class<? extends Annotation>> interStageInputAnnotations; public final ImmutableList<MethodSpec> extraMethods; public final ImmutableList<TypeName> exceptions; private DelegateMethodDescription(Builder builder) { annotations = builder.annotations; accessType = builder.accessType; returnType = builder.returnType; name = builder.name; definedParameterTypes = builder.definedParameterTypes; optionalParameterTypes = builder.optionalParameterTypes; interStageInputAnnotations = builder.interStageInputAnnotations; extraMethods = builder.extraMethods; exceptions = builder.exceptions; } public static Builder newBuilder() { return new Builder(); } public static class Builder { private ImmutableList<AnnotationSpec> annotations; private Modifier accessType; private TypeName returnType; private String name; private ImmutableList<TypeName> definedParameterTypes; private ImmutableList<OptionalParameterType> optionalParameterTypes; private ImmutableList<Class<? extends Annotation>> interStageInputAnnotations; private ImmutableList<MethodSpec> extraMethods; private ImmutableList<TypeName> exceptions; private Builder() { } public Builder annotations(ImmutableList<AnnotationSpec> annotations) { this.annotations = annotations; return this; } public Builder accessType(Modifier accessType) { this.accessType = accessType; return this; } public Builder returnType(TypeName returnType) { this.returnType = returnType; return this; } public Builder name(String name) { this.name = name; return this; } public Builder definedParameterTypes(ImmutableList<TypeName> parameterTypes) { this.definedParameterTypes = parameterTypes; return this; } public Builder optionalParameterTypes( ImmutableList<OptionalParameterType> optionalParameterTypes) { this.optionalParameterTypes = optionalParameterTypes; return this; } public Builder interStageInputAnnotations( ImmutableList<Class<? extends Annotation>> interStageInputAnnotations) { this.interStageInputAnnotations = interStageInputAnnotations; return this; } /** * A list of extra methods that should be generate when this method description is used. */ public Builder extraMethods(ImmutableList<MethodSpec> extraMethods) { this.extraMethods = extraMethods; return this; } public Builder exceptions(ImmutableList<TypeName> exceptions) { this.exceptions = exceptions; return this; } public DelegateMethodDescription build() { validate(); initFieldsIfRequired(); return new DelegateMethodDescription(this); } private void validate() { if (accessType == null) { throw new IllegalStateException("Access type must be specified"); } if (returnType == null) { throw new IllegalStateException("Return type must be specified"); } if (name == null) { throw new IllegalStateException("Name must be specified"); } if (optionalParameterTypes == null) { throw new IllegalStateException("Optional parameter types must be specified"); } } private void initFieldsIfRequired() { if (annotations == null) { annotations = ImmutableList.of(); } if (definedParameterTypes == null) { definedParameterTypes = ImmutableList.of(); } if (interStageInputAnnotations == null) { interStageInputAnnotations = ImmutableList.of(); } if (extraMethods == null) { extraMethods = ImmutableList.of(); } if (exceptions == null) { exceptions = ImmutableList.of(); } } } }