Skip to content

Commit 5a0e9be

Browse files
committed
feat(spawn-application): uptake DI binding API improvements
1 parent a3e0feb commit 5a0e9be

2 files changed

Lines changed: 15 additions & 45 deletions

File tree

spawn-application/src/main/java/build/spawn/application/AbstractTemplatedLauncher.java

Lines changed: 14 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import build.base.commandline.CommandLine;
2424
import build.base.configuration.Configuration;
2525
import build.base.configuration.ConfigurationBuilder;
26-
import build.base.foundation.Introspection;
2726
import build.base.logging.Logger;
2827
import build.base.naming.UniqueNameGenerator;
2928
import build.base.option.TemporaryDirectory;
@@ -34,7 +33,6 @@
3433
import build.base.table.option.RowComparator;
3534
import build.base.table.option.TableName;
3635
import build.codemodel.foundation.usage.GenericTypeUsage;
37-
import build.codemodel.foundation.usage.NamedTypeUsage;
3836
import build.codemodel.injection.Binding;
3937
import build.codemodel.injection.Context;
4038
import build.codemodel.injection.Dependency;
@@ -52,6 +50,7 @@
5250
import java.util.HashMap;
5351
import java.util.Iterator;
5452
import java.util.LinkedHashSet;
53+
import java.util.List;
5554
import java.util.Objects;
5655
import java.util.Optional;
5756
import java.util.Set;
@@ -243,68 +242,41 @@ public A launch(final P platform,
243242

244243
// allow the process interfaces to be used for injection
245244
launchContext.bind((Class) process.getClass()).to(process);
246-
247-
Introspection.getAll(process.getClass(), Class::getInterfaces)
248-
.filter(i -> !i.equals(Addressable.class))
249-
.forEach(i -> launchContext.bind((Class) i).to(process));
245+
launchContext.bind(process).asAllInterfaces(i -> !i.equals(Addressable.class));
250246

251247
// instantiate individual facets
252248
final Set<Facet<?>> facets = launchOptions.stream(Facet.class)
253249
.map(facet -> (Facet<?>) facet)
254250
.map(facet -> {
255251
final Object implementation = facet.getFactory().apply(launchContext);
256252

257-
// allow injection of facets
253+
// allow injection of facets individually and as Iterable<T>
258254
launchContext.bind((Class<Object>) facet.getInterface()).to(implementation);
255+
launchContext.bindSet((Class<Object>) facet.getInterface()).add(implementation);
259256

260257
// create a synthetic Facet that always resolves to the same implementation
261258
return Facet.of(facet.getInterface(), _ -> facet.getInterface().cast(implementation));
262259
})
263260
.collect(Collectors.toSet());
264261

265-
// allow Iterable<T> to be resolved for injection where T is implemented by zero or more Facets.
262+
// fallback: return an empty Iterable<T> for any T not populated via bindSet above
266263
launchContext.addResolver(new Resolver<Iterable<Object>>() {
267264
@Override
268265
public Optional<? extends Binding<Iterable<Object>>> resolve(final Dependency dependency) {
269-
270266
if (dependency.typeUsage() instanceof GenericTypeUsage genericTypeUsage
271267
&& genericTypeUsage.typeName().canonicalName().equals(Iterable.class.getCanonicalName())
272268
&& genericTypeUsage.parameters().count() == 1) {
273-
274-
final var parameterTypeUsage = genericTypeUsage.parameters()
275-
.findFirst()
276-
.orElseThrow();
277-
278-
if (parameterTypeUsage instanceof NamedTypeUsage namedTypeUsage) {
279-
try {
280-
final var parameterClass = this.getClass()
281-
.getClassLoader()
282-
.loadClass(namedTypeUsage.typeName().canonicalName());
283-
284-
// find the Facets that implement T
285-
final var list = facets.stream()
286-
.map(facet -> parameterClass.cast(facet.getFactory().apply(launchContext)))
287-
.filter(parameterClass::isInstance)
288-
.toList();
289-
290-
return Optional.of(new ValueBinding<Iterable<Object>>() {
291-
@Override
292-
@SuppressWarnings("unchecked")
293-
public Iterable<Object> value() {
294-
return (Iterable<Object>) list;
295-
}
296-
297-
@Override
298-
public Dependency dependency() {
299-
return dependency;
300-
}
301-
});
269+
return Optional.of(new ValueBinding<Iterable<Object>>() {
270+
@Override
271+
public Iterable<Object> value() {
272+
return List.of();
302273
}
303-
catch (final ClassNotFoundException e) {
304-
LOGGER.debug("Could not load class [{0}] for Iterable injection resolution",
305-
namedTypeUsage.typeName().canonicalName(), e);
274+
275+
@Override
276+
public Dependency dependency() {
277+
return dependency;
306278
}
307-
}
279+
});
308280
}
309281

310282
return Optional.empty();

spawn-application/src/main/java/build/spawn/application/AbstractTemplatedPlatform.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ public Configuration configuration() {
172172
}
173173

174174
@Override
175-
@SuppressWarnings({"unchecked", "rawtypes"})
176175
public Context createContext(final Class<? extends Application> applicationClass,
177176
final Configuration configuration) {
178177

@@ -189,8 +188,7 @@ public Context createContext(final Class<? extends Application> applicationClass
189188
context.bind(InjectionFramework.class).to(this.injectionFramework);
190189

191190
// allow all interfaces of the Platform to be injected
192-
Introspection.getAll(getClass(), Class::getInterfaces)
193-
.forEach(i -> context.bind((Class) i).to(this));
191+
context.bind(this).asAllInterfaces();
194192

195193
// allows the Platform Server to be injected
196194
context.bind(Server.class).to(this.server);

0 commit comments

Comments
 (0)