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 java.lang.annotation.Annotation;
37 import java.util.Collection;
38 import java.util.Optional;
39 import java.util.function.Consumer;
40 import java.util.function.Function;
41 import java.util.stream.Stream;
42
43 import com.google.inject.Binding;
44 import com.google.inject.Key;
45 import com.google.inject.Scope;
46 import com.google.inject.internal.Scoping;
47 import com.google.inject.spi.ConstructorBinding;
48 import com.google.inject.spi.DefaultBindingScopingVisitor;
49 import com.google.inject.spi.DefaultBindingTargetVisitor;
50 import com.google.inject.spi.Element;
51 import com.google.inject.spi.LinkedKeyBinding;
52 import com.google.inject.spi.ProviderInstanceBinding;
53 import com.google.inject.spi.ProviderKeyBinding;
54 import com.google.inject.spi.UntargettedBinding;
55
56
57
58
59
60
61
62
63
64
65
66
67 public class GuiceSpi {
68
69
70
71
72
73
74
75
76 public static Stream<Binding> getBindings(Collection<Element> elements) {
77 return elements.stream()
78 .filter(element -> element instanceof Binding)
79 .map(element -> (Binding) element);
80 }
81
82 public static <T> Optional<Binding<T>> findBinding(Collection<Element> elements, Key<T> key) {
83 return getBindings(elements).filter(binding -> binding.getKey().equals(key)).map(binding -> (Binding<T>) binding).findFirst();
84 }
85
86 public static <T> Class<? super T> rawType(Key<T> key) {
87 return key.getTypeLiteral().getRawType();
88 }
89
90
91
92
93
94 public static Scoping resolveScope(Binding<?> currentBinding) {
95 return currentBinding.acceptScopingVisitor(new DefaultBindingScopingVisitor<Scoping>() {
96 @Override
97 public Scoping visitEagerSingleton() {
98 return Scoping.EAGER_SINGLETON;
99 }
100
101 @Override
102 public Scoping visitScopeAnnotation(Class<? extends Annotation> scopeAnnotation) {
103 return Scoping.forAnnotation(scopeAnnotation);
104 }
105
106 @Override
107 public Scoping visitScope(Scope scope) {
108 return Scoping.forInstance(scope);
109 }
110
111 @Override
112 public Scoping visitNoScoping() {
113 return Scoping.UNSCOPED;
114 }
115 });
116 }
117
118
119
120
121 public static <R> BindingVisitor<R> inspect(Binding<?> binding) {
122 return new BindingVisitor<>(binding);
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138 public static class BindingVisitor<R> {
139
140 private final Binding<?> binding;
141 private Function<LinkedKeyBinding, R> linkedKeyBindingHandler = binding -> null;
142 private Function<ProviderKeyBinding, R> providerKeyBindingHandler = binding -> null;
143 private Function<ProviderInstanceBinding, R> providerInstanceBindingHandler = binding -> null;
144 private Function<UntargettedBinding, R> untargettedBindingHandler = binding -> null;
145 private Function<ConstructorBinding<?>,R> constructorBindingHandler = binding -> null;
146
147 private BindingVisitor(Binding<?> binding) {
148 this.binding = binding;
149 }
150
151 public BindingVisitor<R> onConstructorBinding(Function<ConstructorBinding<?>, R> handler) {
152 this.constructorBindingHandler = handler;
153 return this;
154 }
155
156 public BindingVisitor<R> consumeConstructorBinding(Consumer<ConstructorBinding<?>> handler) {
157 this.constructorBindingHandler = constructorBinding -> {
158 handler.accept(constructorBinding);
159 return null;
160 };
161
162 return this;
163 }
164
165 public BindingVisitor<R> onLinkedBinding(Function<LinkedKeyBinding, R> handler) {
166 this.linkedKeyBindingHandler = handler;
167 return this;
168 }
169
170 public BindingVisitor<R> consumeLinkedBinding(Consumer<LinkedKeyBinding> handler) {
171 this.linkedKeyBindingHandler = binding -> {
172 handler.accept(binding);
173 return null;
174 };
175 return this;
176 }
177
178 public BindingVisitor<R> onProviderKeyBinding(Function<ProviderKeyBinding, R> handler) {
179 this.providerKeyBindingHandler = handler;
180 return this;
181 }
182
183 public BindingVisitor<R> onProviderInstanceBinding(Function<ProviderInstanceBinding, R> handler) {
184 this.providerInstanceBindingHandler = handler;
185 return this;
186 }
187
188 public BindingVisitor<R> onUntargettedBinding(Function<UntargettedBinding, R> handler) {
189 this.untargettedBindingHandler = handler;
190 return this;
191 }
192
193 public BindingVisitor<R> consumeUntargettedBinding(Consumer<UntargettedBinding<?>> handler) {
194 this.untargettedBindingHandler = untargettedBinding -> {
195 handler.accept(untargettedBinding);
196 return null;
197 };
198
199 return this;
200 }
201
202 public BindingVisitor<R> consumeProviderInstanceBinding(Consumer<ProviderInstanceBinding> handler) {
203 this.providerInstanceBindingHandler = binding -> {
204 handler.accept(binding);
205 return null;
206 };
207 return this;
208 }
209
210 public <T> BindingVisitor<R> consumeProviderKeyBinding(Consumer<ProviderKeyBinding<T>> handler) {
211 this.providerKeyBindingHandler = binding -> {
212 handler.accept(binding);
213 return null;
214 };
215 return this;
216 }
217
218 public Optional<R> visit() {
219 return binding.acceptTargetVisitor(new DefaultBindingTargetVisitor<Object, Optional<R>>() {
220 @Override
221 public Optional<R> visit(ConstructorBinding<?> constructorBinding) {
222 return Optional.ofNullable(constructorBindingHandler.apply(constructorBinding));
223 }
224
225 @Override
226 public Optional<R> visit(ProviderKeyBinding<?> providerKeyBinding) {
227 return Optional.ofNullable(providerKeyBindingHandler.apply(providerKeyBinding));
228 }
229
230 @Override
231 public Optional<R> visit(LinkedKeyBinding<?> linkedKeyBinding) {
232 return Optional.ofNullable(linkedKeyBindingHandler.apply(linkedKeyBinding));
233 }
234
235 @Override
236 public Optional<R> visit(ProviderInstanceBinding<?> providerInstanceBinding) {
237 return Optional.ofNullable(providerInstanceBindingHandler.apply(providerInstanceBinding));
238 }
239
240 @Override
241 public Optional<R> visit(UntargettedBinding<?> untargettedBinding) {
242 return Optional.ofNullable(untargettedBindingHandler.apply(untargettedBinding));
243 }
244
245 @Override
246 protected Optional<R> visitOther(Binding<?> binding) {
247 return Optional.empty();
248 }
249 });
250 };
251 }
252 }