29
29
import org .junit .gen5 .engine .junit5 .extension .TestInfoParameterResolver ;
30
30
31
31
/**
32
- * A {@code TestExtensionRegistry registry} serves to hold all registered extensions (i.e. instances of
33
- * {@linkplain ExtensionPoint}) for a given {@linkplain org.junit.gen5.engine.Container} or
34
- * {@linkplain org.junit.gen5.engine.Leaf}. A registry has a reference to a parent registry and all lookups are done in
35
- * itself and in its parent and thereby all its ancestors. Do not confuse with {@linkplain ExtensionRegistry} which is
36
- * an interface used by {@linkplain ExtensionRegistrar}
32
+ * A {@code TestExtensionRegistry} holds all registered extensions (i.e.
33
+ * instances of {@link ExtensionPoint}) for a given
34
+ * {@link org.junit.gen5.engine.Container} or {@link org.junit.gen5.engine.Leaf}.
35
+ *
36
+ * <p>A registry has a reference to its parent registry, and all lookups are
37
+ * performed first in the current registry itself and then in its parent and
38
+ * thereby all its ancestors.
39
+ *
40
+ * <p>Do not confuse this engine-specific {@code TestExtensionRegistry} with
41
+ * the {@link ExtensionRegistry} which is used by an {@link ExtensionRegistrar}.
37
42
*
38
43
* @since 5.0
39
44
*/
@@ -44,88 +49,94 @@ public enum ApplicationOrder {
44
49
}
45
50
46
51
/**
47
- * Used to create and populate a new registry from a list of extensions and a parent.
52
+ * Factory for creating and populating a new registry from a list of
53
+ * extension types and a parent registry.
48
54
*
49
- * @param parentRegistry The parent registry to be used.
50
- * @param extensionClasses The extensions to be registered in the new registry
51
- * @return a new TestExtensionRegistry
55
+ * @param parentRegistry the parent registry to be used
56
+ * @param extensionTypes the types of extensions to be registered in
57
+ * the new registry
58
+ * @return a new {@code TestExtensionRegistry}
52
59
*/
53
60
public static TestExtensionRegistry newRegistryFrom (TestExtensionRegistry parentRegistry ,
54
- List <Class <? extends TestExtension >> extensionClasses ) {
61
+ List <Class <? extends TestExtension >> extensionTypes ) {
62
+
55
63
TestExtensionRegistry newTestExtensionRegistry = new TestExtensionRegistry (parentRegistry );
56
- extensionClasses .forEach (newTestExtensionRegistry ::addExtension );
64
+ extensionTypes .forEach (newTestExtensionRegistry ::registerExtension );
57
65
return newTestExtensionRegistry ;
58
66
}
59
67
60
- private static final List <Class <? extends TestExtension >> defaultExtensionClasses = Collections .unmodifiableList (
68
+ private static final List <Class <? extends TestExtension >> defaultExtensionTypes = Collections .unmodifiableList (
61
69
Arrays .asList (DisabledCondition .class , TestInfoParameterResolver .class ));
62
70
63
71
/**
64
- * @return all extension classes that are added by default to all root registries
72
+ * @return the list of all extension types that are added by default to all root registries
65
73
*/
66
- public static List <Class <? extends TestExtension >> getDefaultExtensionClasses () {
67
- return defaultExtensionClasses ;
74
+ static List <Class <? extends TestExtension >> getDefaultExtensionTypes () {
75
+ return defaultExtensionTypes ;
68
76
}
69
77
70
- private final Set <Class <? extends TestExtension >> registeredExtensionClasses = new LinkedHashSet <>();
78
+ private final Set <Class <? extends TestExtension >> registeredExtensionTypes = new LinkedHashSet <>();
71
79
72
80
private final List <RegisteredExtensionPoint <?>> registeredExtensionPoints = new ArrayList <>();
73
81
82
+ private final ExtensionRegistry delegatingExtensionRegistry = new DelegatingExtensionRegistry ();
83
+
74
84
private final Optional <TestExtensionRegistry > parent ;
75
85
76
86
public TestExtensionRegistry () {
77
87
this (null );
78
88
}
79
89
80
- public TestExtensionRegistry (TestExtensionRegistry parent ) {
90
+ TestExtensionRegistry (TestExtensionRegistry parent ) {
81
91
this .parent = Optional .ofNullable (parent );
82
92
if (!this .parent .isPresent ()) {
83
93
addDefaultExtensions ();
84
94
}
85
95
}
86
96
87
97
private void addDefaultExtensions () {
88
- getDefaultExtensionClasses ().stream ().forEach (this ::addExtension );
98
+ getDefaultExtensionTypes ().stream ().forEach (this ::registerExtension );
89
99
}
90
100
91
101
/**
92
- * @return all extension classes registered in this registry or one of its ancestors
102
+ * @return all extension types registered in this registry or one of its ancestors
93
103
*/
94
- public Set <Class <? extends TestExtension >> getRegisteredExtensionClasses () {
95
- Set <Class <? extends TestExtension >> allRegisteredExtensionClasses = new LinkedHashSet <>();
104
+ Set <Class <? extends TestExtension >> getRegisteredExtensionTypes () {
105
+ Set <Class <? extends TestExtension >> allRegisteredExtensionTypes = new LinkedHashSet <>();
96
106
this .parent .ifPresent (
97
- parentRegistry -> allRegisteredExtensionClasses .addAll (parentRegistry .getRegisteredExtensionClasses ()));
98
- allRegisteredExtensionClasses .addAll (this .registeredExtensionClasses );
99
- return Collections .unmodifiableSet (allRegisteredExtensionClasses );
107
+ parentRegistry -> allRegisteredExtensionTypes .addAll (parentRegistry .getRegisteredExtensionTypes ()));
108
+ allRegisteredExtensionTypes .addAll (this .registeredExtensionTypes );
109
+ return Collections .unmodifiableSet (allRegisteredExtensionTypes );
100
110
}
101
111
102
112
@ SuppressWarnings ("unchecked" )
103
- private <T extends ExtensionPoint > List <RegisteredExtensionPoint <T >> getRegisteredExtensionPoints (
104
- Class <T > extensionClass ) {
113
+ private <E extends ExtensionPoint > List <RegisteredExtensionPoint <E >> getRegisteredExtensionPoints (
114
+ Class <E > extensionType ) {
105
115
106
- List <RegisteredExtensionPoint <T >> allExtensionPoints = new ArrayList <>();
116
+ List <RegisteredExtensionPoint <E >> allExtensionPoints = new ArrayList <>();
107
117
this .parent .ifPresent (
108
- parentRegistry -> allExtensionPoints .addAll (parentRegistry .getRegisteredExtensionPoints (extensionClass )));
118
+ parentRegistry -> allExtensionPoints .addAll (parentRegistry .getRegisteredExtensionPoints (extensionType )));
109
119
110
- //@formatter:off
111
- registeredExtensionPoints .stream ()
112
- .filter (registeredExtensionPoint -> extensionClass .isAssignableFrom (registeredExtensionPoint .getExtensionPoint ().getClass ()))
113
- .forEach (extensionPoint -> allExtensionPoints .add ((RegisteredExtensionPoint <T >) extensionPoint ));
114
- //@formatter:on
120
+ // @formatter:off
121
+ this . registeredExtensionPoints .stream ()
122
+ .filter (registeredExtensionPoint -> extensionType .isAssignableFrom (registeredExtensionPoint .getExtensionPoint ().getClass ()))
123
+ .forEach (extensionPoint -> allExtensionPoints .add ((RegisteredExtensionPoint <E >) extensionPoint ));
124
+ // @formatter:on
115
125
116
126
return allExtensionPoints ;
117
127
}
118
128
119
129
/**
120
- * Return a stream for iterating all registered extension points.
130
+ * Return a stream for iterating over all registered extension points
131
+ * of the specified type.
121
132
*
122
- * @param <T> The exact {@link ExtensionPoint} for which to find all extensions
123
- * @param extensionClass The {@link ExtensionPoint} class
124
- * @param order The order in which to apply the extension points after sorting. FORWARD or BACKWARD.
133
+ * @param extensionType the type of {@link ExtensionPoint} to stream
134
+ * @param order the order in which to apply the extension points after sorting
125
135
*/
126
- public <T extends ExtensionPoint > Stream <RegisteredExtensionPoint <T >> stream (Class <T > extensionClass ,
136
+ public <E extends ExtensionPoint > Stream <RegisteredExtensionPoint <E >> stream (Class <E > extensionType ,
127
137
ApplicationOrder order ) {
128
- List <RegisteredExtensionPoint <T >> registeredExtensionPoints = getRegisteredExtensionPoints (extensionClass );
138
+
139
+ List <RegisteredExtensionPoint <E >> registeredExtensionPoints = getRegisteredExtensionPoints (extensionType );
129
140
new ExtensionPointSorter ().sort (registeredExtensionPoints );
130
141
if (order == ApplicationOrder .BACKWARD ) {
131
142
Collections .reverse (registeredExtensionPoints );
@@ -134,58 +145,64 @@ public <T extends ExtensionPoint> Stream<RegisteredExtensionPoint<T>> stream(Cla
134
145
}
135
146
136
147
/**
137
- * Register an extension class which can be either an {@linkplain ExtensionPoint} implementatio or an
138
- * {@linkplain ExtensionRegistrar}
148
+ * Instantiate an extension of the given type using its default constructor,
149
+ * and register the extension in this registry.
150
+ *
151
+ * <p>If an extension of the given type already exists in this registry,
152
+ * a new extension will not be registered.
139
153
*
140
- * @param extensionClass The test extension class to be registered
154
+ * <p>The extension type can be either an {@link ExtensionPoint} or an
155
+ * {@link ExtensionRegistrar}.
156
+ *
157
+ * @param extensionType the type extension to register
141
158
*/
142
- public void addExtension (Class <? extends TestExtension > extensionClass ) {
143
- boolean extensionExists = getRegisteredExtensionClasses ().stream ().anyMatch (
144
- registeredClass -> registeredClass .equals (extensionClass ));
145
- if (!extensionExists ) {
146
- TestExtension testExtension = ReflectionUtils .newInstance (extensionClass );
147
- registerExtensionPointImplementors (testExtension );
148
- registerFromExtensionRegistrar (testExtension );
149
- this .registeredExtensionClasses .add (extensionClass );
150
- }
151
- }
159
+ void registerExtension (Class <? extends TestExtension > extensionType ) {
152
160
153
- private void registerFromExtensionRegistrar (TestExtension testExtension ) {
154
- if (testExtension instanceof ExtensionRegistrar ) {
155
- ExtensionRegistrar extensionRegistrar = (ExtensionRegistrar ) testExtension ;
156
- ExtensionRegistry extensionRegistry = createExtensionRegistry (extensionRegistrar );
157
- extensionRegistrar .registerExtensions (extensionRegistry );
158
- }
159
- }
161
+ boolean extensionAlreadyRegistered = getRegisteredExtensionTypes ().stream ().anyMatch (
162
+ registeredType -> registeredType .equals (extensionType ));
160
163
161
- private TestExtensionRegistry .LocalExtensionRegistry createExtensionRegistry (Object extensionInstance ) {
162
- return new TestExtensionRegistry .LocalExtensionRegistry (extensionInstance );
164
+ if (!extensionAlreadyRegistered ) {
165
+ TestExtension testExtension = ReflectionUtils .newInstance (extensionType );
166
+ registerExtensionPoint (testExtension );
167
+ registerExtensionPointsFromRegistrar (testExtension );
168
+ this .registeredExtensionTypes .add (extensionType );
169
+ }
163
170
}
164
171
165
- private void registerExtensionPointImplementors (TestExtension testExtension ) {
172
+ private void registerExtensionPoint (TestExtension testExtension ) {
173
+ // TODO Determine why TestExtensions are not supported.
166
174
if (testExtension instanceof ExtensionPoint ) {
167
- ExtensionPoint extension = (ExtensionPoint ) testExtension ;
168
- registerExtension (extension , Position .DEFAULT , testExtension );
175
+ registerExtensionPoint ((ExtensionPoint ) testExtension );
169
176
}
170
177
}
171
178
172
- public <E extends ExtensionPoint > void registerExtension (E extension , Position position , Object extensionInstance ) {
173
- RegisteredExtensionPoint <E > registeredExtensionPoint = new RegisteredExtensionPoint <>(extension , position ,
174
- extensionInstance );
175
- registeredExtensionPoints .add (registeredExtensionPoint );
179
+ public void registerExtensionPoint (ExtensionPoint extension ) {
180
+ registerExtensionPoint (extension , Position .DEFAULT );
176
181
}
177
182
178
- private class LocalExtensionRegistry implements ExtensionRegistry {
179
-
180
- private Object extensionInstance ;
183
+ void registerExtensionPoint ( ExtensionPoint extension , Position position ) {
184
+ this . registeredExtensionPoints . add ( new RegisteredExtensionPoint <>( extension , position ));
185
+ }
181
186
182
- private LocalExtensionRegistry (Object extensionInstance ) {
183
- this .extensionInstance = extensionInstance ;
187
+ private void registerExtensionPointsFromRegistrar (TestExtension testExtension ) {
188
+ if (testExtension instanceof ExtensionRegistrar ) {
189
+ ExtensionRegistrar extensionRegistrar = (ExtensionRegistrar ) testExtension ;
190
+ extensionRegistrar .registerExtensions (this .delegatingExtensionRegistry );
184
191
}
192
+ }
193
+
194
+ /**
195
+ * {@link ExtensionRegistry} which internally delegates to the enclosing
196
+ * {@link TestExtensionRegistry}: used in order to allow an
197
+ * {@link ExtensionRegistrar} to populate a {@link TestExtensionRegistry}
198
+ * via the {@code ExtensionRegistry} API.
199
+ */
200
+ private class DelegatingExtensionRegistry implements ExtensionRegistry {
185
201
186
202
@ Override
187
203
public <E extends ExtensionPoint > void register (E extension , Class <E > extensionPointType , Position position ) {
188
- registerExtension (extension , position , extensionInstance );
204
+ registerExtensionPoint (extension , position );
189
205
}
190
206
}
207
+
191
208
}
0 commit comments