1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.framework.ioc;
35
36 import static info.magnolia.ui.framework.ioc.GuiceSpi.rawType;
37
38 import info.magnolia.objectfactory.ComponentProvider;
39
40 import java.lang.annotation.Annotation;
41 import java.util.ArrayList;
42 import java.util.List;
43 import java.util.Optional;
44 import java.util.function.Consumer;
45
46 import com.google.inject.AbstractModule;
47 import com.google.inject.Binding;
48 import com.google.inject.Inject;
49 import com.google.inject.Injector;
50 import com.google.inject.Key;
51 import com.google.inject.Module;
52 import com.google.inject.binder.ScopedBindingBuilder;
53 import com.google.inject.internal.Annotations;
54 import com.google.inject.internal.Errors;
55 import com.google.inject.internal.Scoping;
56 import com.google.inject.spi.Element;
57 import com.google.inject.spi.Elements;
58
59
60
61
62
63 final public class ProduceNewInstancesWithComponentProvider extends AbstractModule {
64
65 private final Module sourceModule;
66
67 ProduceNewInstancesWithComponentProvider(Module sourceModule) {
68 this.sourceModule = sourceModule;
69 }
70
71 @Override
72 protected void configure() {
73 List<Element> elements = Elements.getElements(sourceModule);
74 List<Key> processedClasses = new ArrayList<>();
75
76 CreateNewInstanceWithComponentProvider newInstanceProvider = new CreateNewInstanceWithComponentProvider();
77 GuiceSpi.getBindings(elements).forEach(binding -> {
78 Consumer<Key> bindingTransformer = targetKey -> {
79 Class targetType = rawType(targetKey);
80 Key rawKey = Key.get(targetType);
81 if (!processedClasses.contains(targetKey)) {
82 processedClasses.add(targetKey);
83 Class<? extends Annotation> scopeAnnotation = Annotations.findScopeAnnotation(new Errors(), targetType);
84 ScopedBindingBuilder bindingBuilder = bind(rawKey).toProvider(() -> newInstanceProvider.newInstance(targetKey));
85 Optional.ofNullable(scopeAnnotation).map(Scoping::forAnnotation).ifPresent(scoping -> scoping.applyTo(bindingBuilder));
86 }
87 };
88
89 GuiceSpi.<ScopedBindingBuilder>inspect(binding)
90 .consumeUntargettedBinding(untargettedBinding -> bindingTransformer.accept(untargettedBinding.getKey()))
91 .consumeConstructorBinding(constructorBinding -> bindingTransformer.accept(constructorBinding.getKey()))
92 .consumeLinkedBinding(linkedKeyBinding -> bindingTransformer.accept(linkedKeyBinding.getLinkedKey())).visit();
93 });
94
95 elements.stream()
96 .filter(element ->
97 !(element instanceof Binding) ||
98 !processedClasses.contains(((Binding) element).getKey()))
99 .forEach(element -> element.applyTo(binder()));
100
101 requestInjection(newInstanceProvider);
102 }
103
104
105
106
107
108
109 static class CreateNewInstanceWithComponentProvider {
110
111 @Inject
112 Injector injector;
113
114 public <T> T newInstance(Key<T> key) {
115 return (T) injector.getInstance(ComponentProvider.class).newInstance(rawType(key));
116 }
117 }
118 }