BeanElementBuilder.java
/*
* Copyright 2017-2021 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.micronaut.inject.ast.beans;
import io.micronaut.core.annotation.AnnotationValue;
import io.micronaut.core.annotation.AnnotationValueBuilder;
import io.micronaut.core.annotation.Experimental;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.annotation.Nullable;
import io.micronaut.inject.ast.ClassElement;
import io.micronaut.inject.ast.Element;
import io.micronaut.inject.ast.ElementQuery;
import io.micronaut.inject.ast.FieldElement;
import io.micronaut.inject.ast.MemberElement;
import io.micronaut.inject.ast.MethodElement;
import java.lang.annotation.Annotation;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* Interface for defining beans at compilation time from an originating element.
*
* @author graemerocher
* @since 3.0.0
*/
@Experimental
public interface BeanElementBuilder extends ConfigurableElement {
/**
* Intercept the bean.
* @param annotationValue The annotation to intercept
* @return This bean method
* @since 3.5.2
*/
default @NonNull BeanElementBuilder intercept(AnnotationValue<?>... annotationValue) {
if (annotationValue != null) {
for (AnnotationValue<?> value : annotationValue) {
annotate(value);
}
}
return this;
}
/**
* @return The originating element
*/
@NonNull
Element getOriginatingElement();
/**
* @return The bean type
*/
@NonNull
ClassElement getBeanType();
/**
* @return The element that produces the bean.
*/
@NonNull
default Element getProducingElement() {
return getBeanType();
}
/**
* Returns the class that declares the bean. In case of a bean defined by a class, that is the bean class directly. In case of a producer method or field, that is the class that declares the producer method or field.
*
* @return The element declares the bean.
*/
@NonNull
default ClassElement getDeclaringElement() {
return getBeanType();
}
/**
* Specifies the bean will be created with the given method element. If
* not specified the bean will be created with {@link ClassElement#getPrimaryConstructor()}.
*
* <p>Note that the method can be a one of the following:</p>
*
* <ul>
* <li>An accessible constructor on the bean type being generated</li>
* <li>An accessible static method on the bean type being generated</li>
* </ul>
*
* @param element The element
* @return This bean builder
*/
@NonNull
BeanElementBuilder createWith(@NonNull MethodElement element);
/**
* Alters the exposed types for the bean limiting the exposed type to the given types.
* @param types 1 or more types to expose
* @return This builder
*/
@NonNull
BeanElementBuilder typed(ClassElement... types);
/**
* Fills the type arguments for the bean with the given types.
* @param types The types
* @return This bean builder
*/
@Override
@NonNull
BeanElementBuilder typeArguments(@NonNull ClassElement... types);
/**
* Fills the type arguments for the given interface or super class with the given types.
* @param type The type or interface. If null, results in a no-op
* @param types The types
* @return This bean builder
*/
@NonNull
BeanElementBuilder typeArgumentsForType(@Nullable ClassElement type, @NonNull ClassElement... types);
/**
* Adds a scope for the given annotation value to the bean.
*
* @param scope The scope
* @return This bean element builder
*/
default @NonNull
BeanElementBuilder scope(@NonNull AnnotationValue<?> scope) {
Objects.requireNonNull(scope, "Scope cannot be null");
annotate(scope.getAnnotationName(), (builder) -> builder.members(scope.getValues()));
return this;
}
/**
* Adds a scope for the given annotation value to the bean.
*
* @param scope The full qualified scope annotation name
* @return This bean element builder
*/
default @NonNull
BeanElementBuilder scope(@NonNull String scope) {
Objects.requireNonNull(scope, "Scope cannot be null");
annotate(scope);
return this;
}
/**
* Allows configuring the bean constructor.
* @param constructorElement The constructor element
* @return This bean builder
*/
@NonNull
BeanElementBuilder withConstructor(@NonNull Consumer<BeanConstructorElement> constructorElement);
/**
* Allows configuring methods of the bean.
* @param methods The {@link ElementQuery} to locate selected methods.
* @param beanMethods A consumer that receives each {@link BeanMethodElement}
* @return This builder
*/
@NonNull
BeanElementBuilder withMethods(
@NonNull ElementQuery<MethodElement> methods,
@NonNull Consumer<BeanMethodElement> beanMethods);
/**
* Allows configuring fields of the bean.
* @param fields The {@link ElementQuery} to locate fields.
* @param beanFields The bean fields
* @return This builder
*/
@NonNull
BeanElementBuilder withFields(
@NonNull ElementQuery<FieldElement> fields,
@NonNull Consumer<BeanFieldElement> beanFields);
/**
* Allows configuring the parameters for the current constructor.
* @param parameters The parameters
* @return This builder
*/
@NonNull
BeanElementBuilder withParameters(Consumer<BeanParameterElement[]> parameters);
@NonNull
@Override
default BeanElementBuilder qualifier(@Nullable String qualifier) {
return (BeanElementBuilder) ConfigurableElement.super.qualifier(qualifier);
}
@NonNull
@Override
default BeanElementBuilder qualifier(@NonNull AnnotationValue<?> qualifier) {
return (BeanElementBuilder) ConfigurableElement.super.qualifier(qualifier);
}
@NonNull
@Override
default <T extends Annotation> BeanElementBuilder annotate(@NonNull String annotationType,
@NonNull Consumer<AnnotationValueBuilder<T>> consumer) {
return (BeanElementBuilder) ConfigurableElement.super.annotate(annotationType, consumer);
}
@Override
default BeanElementBuilder removeAnnotation(@NonNull String annotationType) {
return (BeanElementBuilder) ConfigurableElement.super.removeAnnotation(annotationType);
}
@Override
default <T extends Annotation> BeanElementBuilder removeAnnotation(@NonNull Class<T> annotationType) {
return (BeanElementBuilder) ConfigurableElement.super.removeAnnotation(annotationType);
}
@Override
default <T extends Annotation> BeanElementBuilder removeAnnotationIf(@NonNull Predicate<AnnotationValue<T>> predicate) {
return (BeanElementBuilder) ConfigurableElement.super.removeAnnotationIf(predicate);
}
@Override
default BeanElementBuilder removeStereotype(@NonNull String annotationType) {
return (BeanElementBuilder) ConfigurableElement.super.removeStereotype(annotationType);
}
@Override
default <T extends Annotation> BeanElementBuilder removeStereotype(@NonNull Class<T> annotationType) {
return (BeanElementBuilder) ConfigurableElement.super.removeStereotype(annotationType);
}
@NonNull
@Override
default BeanElementBuilder annotate(@NonNull String annotationType) {
return (BeanElementBuilder) ConfigurableElement.super.annotate(annotationType);
}
@NonNull
@Override
default <T extends Annotation> BeanElementBuilder annotate(@NonNull Class<T> annotationType,
@NonNull Consumer<AnnotationValueBuilder<T>> consumer) {
return (BeanElementBuilder) ConfigurableElement.super.annotate(annotationType, consumer);
}
@NonNull
@Override
default <T extends Annotation> BeanElementBuilder annotate(@NonNull Class<T> annotationType) {
return (BeanElementBuilder) ConfigurableElement.super.annotate(annotationType);
}
/**
* Dependency inject this bean.
* @return this bean builder
*/
BeanElementBuilder inject();
/**
* Produce additional beans from the given methods.
* @param methodsOrFields The {@link io.micronaut.inject.ast.ElementQuery} representing the methods or fields
* @param childBeanBuilder Configure the child bean builder
* @return This bean builder
* @param <E> A type variable to
*/
<E extends MemberElement> BeanElementBuilder produceBeans(ElementQuery<E> methodsOrFields, @Nullable Consumer<BeanElementBuilder> childBeanBuilder);
/**
* Produce additional beans from the given methods.
* @param methodsOrFields The {@link io.micronaut.inject.ast.ElementQuery} representing the methods or fields
* @return This bean builder
* @param <E> A type variable to
*/
default <E extends MemberElement> BeanElementBuilder produceBeans(ElementQuery<E> methodsOrFields) {
return produceBeans(methodsOrFields, null);
}
}