Skip to content

Commit cba3bc8

Browse files
authored
1 parent 1d7abff commit cba3bc8

13 files changed

Lines changed: 276 additions & 43 deletions

File tree

pico/api/src/test/java/io/helidon/pico/api/DefaultQualifierAndValueTest.java renamed to pico/api/src/main/java/io/helidon/pico/api/ClassNamed.java

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,27 @@
1616

1717
package io.helidon.pico.api;
1818

19-
import io.helidon.common.types.AnnotationAndValueDefault;
19+
import java.lang.annotation.Documented;
20+
import java.lang.annotation.Retention;
21+
import java.lang.annotation.RetentionPolicy;
2022

2123
import jakarta.inject.Named;
22-
import org.junit.jupiter.api.Test;
24+
import jakarta.inject.Qualifier;
2325

24-
import static org.hamcrest.CoreMatchers.is;
25-
import static org.hamcrest.MatcherAssert.assertThat;
26-
27-
class DefaultQualifierAndValueTest {
26+
/**
27+
* This annotation is effectively the same as {@link jakarta.inject.Named} where the {@link Named#value()} is a {@link Class}
28+
* name instead of a {@link String}.
29+
*/
30+
@Qualifier
31+
@Documented
32+
@Retention(RetentionPolicy.RUNTIME)
33+
public @interface ClassNamed {
2834

29-
@Test
30-
void buildAndCompare() {
31-
QualifierAndValueDefault qav1 = QualifierAndValueDefault.builder()
32-
.type(Named.class)
33-
.value("x.y")
34-
.build();
35-
AnnotationAndValueDefault qav2 = QualifierAndValueDefault.builder()
36-
.type(Named.class)
37-
.value("x.y")
38-
.build();
39-
assertThat(qav1.compareTo(qav2),
40-
is(0));
41-
}
35+
/**
36+
* The class used will function as the name.
37+
*
38+
* @return the class
39+
*/
40+
Class<?> value();
4241

4342
}

pico/api/src/main/java/io/helidon/pico/api/QualifierAndValueDefault.java

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import io.helidon.common.types.TypeName;
2727
import io.helidon.common.types.TypeNameDefault;
2828

29+
import jakarta.inject.Named;
30+
2931
/**
3032
* Describes a {@link jakarta.inject.Qualifier} type annotation associated with a service being provided or dependant upon.
3133
* In Pico these are generally determined at compile time to avoid any use of reflection at runtime.
@@ -54,6 +56,43 @@ public static QualifierAndValueDefault createNamed(String name) {
5456
return builder().typeName(CommonQualifiers.NAMED).value(name).build();
5557
}
5658

59+
/**
60+
* Creates a {@link jakarta.inject.Named} qualifier.
61+
*
62+
* @param name the name
63+
* @return named qualifier
64+
*/
65+
public static QualifierAndValueDefault createNamed(Named name) {
66+
Objects.requireNonNull(name);
67+
QualifierAndValueDefault.Builder builder = builder().typeName(CommonQualifiers.NAMED);
68+
if (!name.value().isEmpty()) {
69+
builder.value(name.value());
70+
}
71+
return builder.build();
72+
}
73+
74+
/**
75+
* Creates a {@link jakarta.inject.Named} qualifier.
76+
*
77+
* @param name the name
78+
* @return named qualifier
79+
*/
80+
public static QualifierAndValueDefault createNamed(ClassNamed name) {
81+
Objects.requireNonNull(name);
82+
return builder().typeName(CommonQualifiers.NAMED).value(name.value().getName()).build();
83+
}
84+
85+
/**
86+
* Creates a {@link jakarta.inject.Named} qualifier.
87+
*
88+
* @param name the name of the class will be used
89+
* @return named qualifier
90+
*/
91+
public static QualifierAndValueDefault createClassNamed(Class<?> name) {
92+
Objects.requireNonNull(name);
93+
return builder().typeName(CommonQualifiers.NAMED).value(name.getName()).build();
94+
}
95+
5796
/**
5897
* Creates a qualifier from an annotation.
5998
*
@@ -62,7 +101,8 @@ public static QualifierAndValueDefault createNamed(String name) {
62101
*/
63102
public static QualifierAndValueDefault create(Class<? extends Annotation> qualifierType) {
64103
Objects.requireNonNull(qualifierType);
65-
return builder().typeName(TypeNameDefault.create(qualifierType)).build();
104+
TypeName qualifierTypeName = maybeNamed(qualifierType.getName());
105+
return builder().typeName(qualifierTypeName).build();
66106
}
67107

68108
/**
@@ -74,7 +114,8 @@ public static QualifierAndValueDefault create(Class<? extends Annotation> qualif
74114
*/
75115
public static QualifierAndValueDefault create(Class<? extends Annotation> qualifierType, String val) {
76116
Objects.requireNonNull(qualifierType);
77-
return builder().typeName(TypeNameDefault.create(qualifierType)).value(val).build();
117+
TypeName qualifierTypeName = maybeNamed(qualifierType.getName());
118+
return builder().typeName(qualifierTypeName).value(val).build();
78119
}
79120

80121
/**
@@ -85,8 +126,9 @@ public static QualifierAndValueDefault create(Class<? extends Annotation> qualif
85126
* @return qualifier
86127
*/
87128
public static QualifierAndValueDefault create(String qualifierTypeName, String val) {
129+
TypeName qualifierType = maybeNamed(qualifierTypeName);
88130
return builder()
89-
.typeName(TypeNameDefault.createFromTypeName(qualifierTypeName))
131+
.typeName(qualifierType)
90132
.value(val)
91133
.build();
92134
}
@@ -99,8 +141,9 @@ public static QualifierAndValueDefault create(String qualifierTypeName, String v
99141
* @return qualifier
100142
*/
101143
public static QualifierAndValueDefault create(TypeName qualifierType, String val) {
144+
TypeName qualifierTypeName = maybeNamed(qualifierType);
102145
return builder()
103-
.typeName(qualifierType)
146+
.typeName(qualifierTypeName)
104147
.value(val)
105148
.build();
106149
}
@@ -113,12 +156,27 @@ public static QualifierAndValueDefault create(TypeName qualifierType, String val
113156
* @return qualifier
114157
*/
115158
public static QualifierAndValueDefault create(TypeName qualifierType, Map<String, String> vals) {
159+
TypeName qualifierTypeName = maybeNamed(qualifierType);
116160
return builder()
117-
.typeName(qualifierType)
161+
.typeName(qualifierTypeName)
118162
.values(vals)
119163
.build();
120164
}
121165

166+
static TypeName maybeNamed(String qualifierTypeName) {
167+
if (qualifierTypeName.equals(ClassNamed.class.getName())) {
168+
return CommonQualifiers.NAMED;
169+
}
170+
return TypeNameDefault.createFromTypeName(qualifierTypeName);
171+
}
172+
173+
static TypeName maybeNamed(TypeName qualifierTypeName) {
174+
if (qualifierTypeName.name().equals(ClassNamed.class.getName())) {
175+
return CommonQualifiers.NAMED;
176+
}
177+
return qualifierTypeName;
178+
}
179+
122180
/**
123181
* Converts from an {@link AnnotationAndValue} to a {@link QualifierAndValue}.
124182
*
@@ -139,7 +197,7 @@ public static QualifierAndValue convert(AnnotationAndValue annotationAndValue) {
139197
}
140198

141199
return builder()
142-
.typeName(annotationAndValue.typeName())
200+
.typeName(maybeNamed(annotationAndValue.typeName()))
143201
.values(values)
144202
.build();
145203
}

pico/api/src/test/java/io/helidon/pico/api/DefaultPicoConfigTest.java renamed to pico/api/src/test/java/io/helidon/pico/api/PicoServicesConfigDefaultTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import static org.hamcrest.Matchers.equalTo;
3030
import static org.hamcrest.Matchers.isEmptyOrNullString;
3131

32-
class DefaultPicoConfigTest {
32+
class PicoServicesConfigDefaultTest {
3333

3434
@AfterEach
3535
void reset() {
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*
2+
* Copyright (c) 2023 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.helidon.pico.api;
18+
19+
import java.lang.annotation.Annotation;
20+
21+
import io.helidon.common.types.AnnotationAndValueDefault;
22+
23+
import jakarta.inject.Named;
24+
import org.junit.jupiter.api.Test;
25+
26+
import static org.hamcrest.CoreMatchers.is;
27+
import static org.hamcrest.CoreMatchers.notNullValue;
28+
import static org.hamcrest.MatcherAssert.assertThat;
29+
30+
class QualifierAndValueDefaultTest {
31+
32+
@Test
33+
void buildAndCompare() {
34+
QualifierAndValueDefault qav1 = QualifierAndValueDefault.builder()
35+
.type(Named.class)
36+
.value("x.y")
37+
.build();
38+
AnnotationAndValueDefault qav2 = QualifierAndValueDefault.builder()
39+
.type(Named.class)
40+
.value("x.y")
41+
.build();
42+
assertThat(qav1.compareTo(qav2),
43+
is(0));
44+
}
45+
46+
@Test
47+
public void buildAndCompareClassNamed() {
48+
QualifierAndValueDefault qav1 = QualifierAndValueDefault.createNamed(new FakeNamed());
49+
QualifierAndValueDefault qav2 = QualifierAndValueDefault.createNamed(new FakeClassNamed());
50+
51+
assertThat(qav1.compareTo(qav2),
52+
is(0));
53+
assertThat(qav2.compareTo(qav1),
54+
is(0));
55+
}
56+
57+
@Named("io.helidon.pico.api.DefaultQualifierAndValueTest")
58+
@ClassNamed(QualifierAndValueDefaultTest.class)
59+
@Test
60+
public void createClassNamed() throws Exception {
61+
QualifierAndValueDefault qav1 = QualifierAndValueDefault.createClassNamed(QualifierAndValueDefaultTest.class);
62+
QualifierAndValueDefault qav2 = QualifierAndValueDefault.builder()
63+
.type(Named.class)
64+
.value(QualifierAndValueDefault.class.getName())
65+
.build();
66+
assertThat(qav1.compareTo(qav2),
67+
is(0));
68+
69+
assertThat("runtime retention expected for " + ClassNamed.class,
70+
getClass().getMethod("createClassNamed").getAnnotation(ClassNamed.class),
71+
notNullValue());
72+
}
73+
74+
class FakeNamed implements Named {
75+
@Override
76+
public String value() {
77+
return QualifierAndValueDefaultTest.class.getName();
78+
}
79+
80+
@Override
81+
public Class<? extends Annotation> annotationType() {
82+
return Named.class;
83+
}
84+
}
85+
86+
class FakeClassNamed implements ClassNamed {
87+
@Override
88+
public Class value() {
89+
return QualifierAndValueDefaultTest.class;
90+
}
91+
92+
@Override
93+
public Class<? extends Annotation> annotationType() {
94+
return ClassNamed.class;
95+
}
96+
}
97+
98+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright (c) 2023 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.helidon.pico.tests.pico;
18+
19+
/**
20+
* For Testing.
21+
*/
22+
public class ClassNamedX {
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright (c) 2023 Oracle and/or its affiliates.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.helidon.pico.tests.pico;
18+
19+
/**
20+
* For Testing.
21+
*/
22+
public class ClassNamedY {
23+
}

pico/tests/resources-pico/src/main/java/io/helidon/pico/tests/pico/interceptor/XImpl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
import java.io.IOException;
2121
import java.util.Optional;
2222

23+
import io.helidon.pico.api.ClassNamed;
2324
import io.helidon.pico.api.ExternalContracts;
25+
import io.helidon.pico.tests.pico.ClassNamedX;
2426
import io.helidon.pico.tests.plain.interceptor.IA;
2527
import io.helidon.pico.tests.plain.interceptor.IB;
2628
import io.helidon.pico.tests.plain.interceptor.InterceptorBasedAnno;
@@ -36,7 +38,7 @@
3638
* Also note that interception was triggered by the presence of the {@link TestNamed} and {@link InterceptorBasedAnno} triggers.
3739
*/
3840
@Singleton
39-
@Named("ClassX")
41+
@ClassNamed(ClassNamedX.class)
4042
@TestNamed("TestNamed-ClassX")
4143
@ExternalContracts(value = Closeable.class, moduleNames = {"test1", "test2"})
4244
@SuppressWarnings("unused")

pico/tests/resources-pico/src/main/java/io/helidon/pico/tests/pico/interceptor/YImpl.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
import java.io.IOException;
2121
import java.util.Optional;
2222

23+
import io.helidon.pico.api.ClassNamed;
2324
import io.helidon.pico.api.ExternalContracts;
25+
import io.helidon.pico.tests.pico.ClassNamedY;
2426
import io.helidon.pico.tests.plain.interceptor.IA;
2527
import io.helidon.pico.tests.plain.interceptor.IB;
2628
import io.helidon.pico.tests.plain.interceptor.InterceptorBasedAnno;
@@ -36,7 +38,7 @@
3638
* Also note that interception was triggered by the presence of the {@link InterceptorBasedAnno} trigger.
3739
*/
3840
@Singleton
39-
@Named("ClassY")
41+
@ClassNamed(ClassNamedY.class)
4042
@ExternalContracts(value = Closeable.class, moduleNames = {"test1", "test2"})
4143
@SuppressWarnings("unused")
4244
public class YImpl implements IB, Closeable {

pico/tests/resources-pico/src/test/java/io/helidon/pico/tests/pico/interceptor/InterceptorRuntimeTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import io.helidon.pico.api.ServiceProvider;
3737
import io.helidon.pico.api.Services;
3838
import io.helidon.pico.testing.ReflectionBasedSingletonServiceProvider;
39+
import io.helidon.pico.tests.pico.ClassNamedY;
3940
import io.helidon.pico.tests.plain.interceptor.IB;
4041
import io.helidon.pico.tests.plain.interceptor.InterceptorBasedAnno;
4142
import io.helidon.pico.tests.plain.interceptor.TestNamedInterceptor;
@@ -168,7 +169,7 @@ void runtimeWithNoInterception() throws Exception {
168169
.lookupFirst(
169170
ServiceInfoCriteriaDefault.builder()
170171
.addContractImplemented(Closeable.class.getName())
171-
.qualifiers(Set.of(create(Named.class, "ClassY")))
172+
.qualifiers(Set.of(create(Named.class, ClassNamedY.class.getName())))
172173
.build());
173174
assertThat(toDescription(yimplProvider),
174175
equalTo("YImpl$$Pico$$Interceptor:INIT"));
@@ -250,7 +251,7 @@ void runtimeWithInterception() throws Exception {
250251
.lookupFirst(
251252
ServiceInfoCriteriaDefault.builder()
252253
.addContractImplemented(Closeable.class.getName())
253-
.qualifiers(Set.of(create(Named.class, "ClassY")))
254+
.qualifiers(Set.of(create(Named.class, ClassNamedY.class.getName())))
254255
.build());
255256
assertThat(toDescription(yimplProvider),
256257
equalTo("YImpl$$Pico$$Interceptor:INIT"));

0 commit comments

Comments
 (0)