From 10757cab89319cd2d00e98f1fa6341eb8977327e Mon Sep 17 00:00:00 2001 From: Rob Bygrave Date: Sat, 11 Mar 2023 11:04:00 +1300 Subject: [PATCH] #312 Follow up for @Requires - read repeatable container annotations - Read the repeatable Container annotations - Move the annotation reading into BeanConditions - Rename the inner repeatable annotations to Container (so IDE autocompletion for Requires* only sees our 2 @RequiresBean and @RequiresProperty annotations --- .../myapp/conditional/BirdFactory.java | 1 + .../myapp/conditional/BirdWatcher.java | 6 ++++ .../inject/generator/BeanConditions.java | 31 +++++++++++++++++-- .../io/avaje/inject/generator/BeanReader.java | 20 +----------- .../avaje/inject/generator/MethodReader.java | 19 +----------- .../avaje/inject/generator/package-info.java | 13 ++------ .../java/io/avaje/inject/RequiresBean.java | 4 +-- .../io/avaje/inject/RequiresProperty.java | 4 +-- 8 files changed, 45 insertions(+), 53 deletions(-) diff --git a/blackbox-test-inject/src/main/java/org/example/myapp/conditional/BirdFactory.java b/blackbox-test-inject/src/main/java/org/example/myapp/conditional/BirdFactory.java index 5fa6a51db..cf53aafa4 100644 --- a/blackbox-test-inject/src/main/java/org/example/myapp/conditional/BirdFactory.java +++ b/blackbox-test-inject/src/main/java/org/example/myapp/conditional/BirdFactory.java @@ -10,6 +10,7 @@ @Factory @RequiresProperty(value = "factory", equalTo = "bird", missingProperties = "neverExisted") +@RequiresProperty(value = "somethingElse", notEqualTo = "testRepeatable") public class BirdFactory { @Bean diff --git a/blackbox-test-inject/src/main/java/org/example/myapp/conditional/BirdWatcher.java b/blackbox-test-inject/src/main/java/org/example/myapp/conditional/BirdWatcher.java index c19492551..d56dde52e 100644 --- a/blackbox-test-inject/src/main/java/org/example/myapp/conditional/BirdWatcher.java +++ b/blackbox-test-inject/src/main/java/org/example/myapp/conditional/BirdWatcher.java @@ -1,8 +1,14 @@ package org.example.myapp.conditional; +import io.avaje.inject.RequiresBean; import jakarta.inject.Singleton; +import java.awt.*; +import java.util.Properties; + @Singleton +@RequiresBean(missingBeans = Properties.class) +@RequiresBean(missingBeans = SystemColor.class) @RequiresBird public class BirdWatcher { diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/BeanConditions.java b/inject-generator/src/main/java/io/avaje/inject/generator/BeanConditions.java index f0601786b..8a83cea3f 100644 --- a/inject-generator/src/main/java/io/avaje/inject/generator/BeanConditions.java +++ b/inject-generator/src/main/java/io/avaje/inject/generator/BeanConditions.java @@ -1,5 +1,7 @@ package io.avaje.inject.generator; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.Element; import java.util.*; final class BeanConditions { @@ -12,13 +14,38 @@ final class BeanConditions { final Map propertyEquals = new HashMap<>(); final Map propertyNotEquals = new HashMap<>(); - void read(RequiresBeanPrism prism) { + + void readAll(Element element) { + readMetaAnnotations(element); + readAllDirect(element); + } + + private void readAllDirect(Element element) { + RequiresBeanPrism.getAllInstancesOn(element).forEach(this::read); + RequiresBeanContainerPrism.getOptionalOn(element).ifPresent( container -> { + container.value().forEach(this::read); + }); + RequiresPropertyPrism.getAllInstancesOn(element).forEach(this::read); + RequiresPropertyContainerPrism.getOptionalOn(element).ifPresent( container -> { + container.value().forEach(this::read); + }); + } + + private void readMetaAnnotations(Element element) { + element.getAnnotationMirrors().forEach(this::findRequiresOnAnnotation); + } + + private void findRequiresOnAnnotation(AnnotationMirror a) { + readAllDirect(a.getAnnotationType().asElement()); + } + + private void read(RequiresBeanPrism prism) { prism.value().forEach(t -> requireTypes.add(t.toString())); prism.missingBeans().forEach(t -> missingTypes.add(t.toString())); qualifierNames.addAll(prism.qualifiers()); } - void read(RequiresPropertyPrism prism) { + private void read(RequiresPropertyPrism prism) { if (!prism.value().isBlank()) { if (!prism.notEqualTo().isBlank()) { propertyNotEquals.put(prism.value(), prism.notEqualTo()); diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/BeanReader.java b/inject-generator/src/main/java/io/avaje/inject/generator/BeanReader.java index 3b3e6eb55..1f7891977 100644 --- a/inject-generator/src/main/java/io/avaje/inject/generator/BeanReader.java +++ b/inject-generator/src/main/java/io/avaje/inject/generator/BeanReader.java @@ -44,10 +44,7 @@ final class BeanReader { this.proxy = ProxyPrism.isPresent(beanType); this.typeReader = new TypeReader(GenericType.parse(type), beanType, importTypes, factory); - beanType.getAnnotationMirrors().forEach(this::findRequiresOnAnnotation); - - RequiresBeanPrism.getAllInstancesOn(beanType).forEach(this::processBeanPrism); - RequiresPropertyPrism.getAllInstancesOn(beanType).forEach(this::processPropertyPrism); + conditions.readAll(beanType); typeReader.process(); this.requestParams = new BeanRequestParams(type); @@ -66,21 +63,6 @@ public String toString() { return beanType.toString(); } - void processBeanPrism(RequiresBeanPrism prism) { - conditions.read(prism); - } - - void processPropertyPrism(RequiresPropertyPrism prism) { - conditions.read(prism); - } - - private void findRequiresOnAnnotation(AnnotationMirror a) { - final var annotationElement = a.getAnnotationType().asElement(); - - RequiresBeanPrism.getAllInstancesOn(annotationElement).forEach(this::processBeanPrism); - RequiresPropertyPrism.getAllInstancesOn(annotationElement).forEach(this::processPropertyPrism); - } - TypeElement beanType() { return beanType; } diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/MethodReader.java b/inject-generator/src/main/java/io/avaje/inject/generator/MethodReader.java index 55f8ab4ef..a3df7899a 100644 --- a/inject-generator/src/main/java/io/avaje/inject/generator/MethodReader.java +++ b/inject-generator/src/main/java/io/avaje/inject/generator/MethodReader.java @@ -47,9 +47,7 @@ final class MethodReader { primary = PrimaryPrism.isPresent(element); secondary = SecondaryPrism.isPresent(element); - element.getAnnotationMirrors().forEach(this::findRequiresOnAnnotation); - RequiresBeanPrism.getAllInstancesOn(element).forEach(this::processBeanPrism); - RequiresPropertyPrism.getAllInstancesOn(element).forEach(this::processPropertyPrism); + conditions.readAll(element); } else { prototype = false; @@ -98,21 +96,6 @@ public String toString() { '}'; } - void processBeanPrism(RequiresBeanPrism prism) { - conditions.read(prism); - } - - void processPropertyPrism(RequiresPropertyPrism prism) { - conditions.read(prism); - } - - private void findRequiresOnAnnotation(AnnotationMirror a) { - final var annotationElement = a.getAnnotationType().asElement(); - - RequiresBeanPrism.getAllInstancesOn(annotationElement).forEach(this::processBeanPrism); - RequiresPropertyPrism.getAllInstancesOn(annotationElement).forEach(this::processPropertyPrism); - } - void addDependsOnGeneric(Set set) { for (MethodParam param : params) { param.addDependsOnGeneric(set); diff --git a/inject-generator/src/main/java/io/avaje/inject/generator/package-info.java b/inject-generator/src/main/java/io/avaje/inject/generator/package-info.java index f4a2171dd..e857df41c 100644 --- a/inject-generator/src/main/java/io/avaje/inject/generator/package-info.java +++ b/inject-generator/src/main/java/io/avaje/inject/generator/package-info.java @@ -18,18 +18,11 @@ @GeneratePrism(Generated.class) @GeneratePrism(RequiresBean.class) @GeneratePrism(RequiresProperty.class) +@GeneratePrism(value = RequiresBean.Container.class, name = "RequiresBeanContainerPrism") +@GeneratePrism(value = RequiresProperty.Container.class, name = "RequiresPropertyContainerPrism") package io.avaje.inject.generator; -import io.avaje.inject.Bean; -import io.avaje.inject.Component; -import io.avaje.inject.Factory; -import io.avaje.inject.InjectModule; -import io.avaje.inject.Primary; -import io.avaje.inject.Prototype; -import io.avaje.inject.QualifiedMap; -import io.avaje.inject.RequiresBean; -import io.avaje.inject.RequiresProperty; -import io.avaje.inject.Secondary; +import io.avaje.inject.*; import io.avaje.inject.aop.Aspect; import io.avaje.inject.spi.DependencyMeta; import io.avaje.inject.spi.Generated; diff --git a/inject/src/main/java/io/avaje/inject/RequiresBean.java b/inject/src/main/java/io/avaje/inject/RequiresBean.java index c83d45b49..93c1ce96e 100644 --- a/inject/src/main/java/io/avaje/inject/RequiresBean.java +++ b/inject/src/main/java/io/avaje/inject/RequiresBean.java @@ -28,7 +28,7 @@ * OtherService} is already registered in the {@link BeanScope}. */ @Retention(RUNTIME) -@Repeatable(RequiresBean.RequireBeans.class) +@Repeatable(RequiresBean.Container.class) @Target({TYPE, METHOD, ANNOTATION_TYPE}) public @interface RequiresBean { @@ -55,7 +55,7 @@ String[] qualifiers() default {}; @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) - @interface RequireBeans { + @interface Container { /** @return The required dependencies */ RequiresBean[] value(); diff --git a/inject/src/main/java/io/avaje/inject/RequiresProperty.java b/inject/src/main/java/io/avaje/inject/RequiresProperty.java index ecf84048c..63d289b43 100644 --- a/inject/src/main/java/io/avaje/inject/RequiresProperty.java +++ b/inject/src/main/java/io/avaje/inject/RequiresProperty.java @@ -29,7 +29,7 @@ * system properties / Avaje Config. */ @Retention(RUNTIME) -@Repeatable(RequiresProperty.RequireProperties.class) +@Repeatable(RequiresProperty.Container.class) @Target({TYPE, METHOD, ANNOTATION_TYPE}) public @interface RequiresProperty { @@ -64,7 +64,7 @@ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) - @interface RequireProperties { + @interface Container { /** @return The required dependencies */ RequiresProperty[] value();