Skip to content

Commit 3a88fac

Browse files
authored
Merge pull request #3 from treblereel/generators_refactoring
Generators refactoring
2 parents 711e522 + b5cb3cb commit 3a88fac

File tree

48 files changed

+1316
-488
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+1316
-488
lines changed

core/src/main/java/io/crysknife/client/internal/AbstractBeanManager.java

+150-121
Original file line numberDiff line numberDiff line change
@@ -19,56 +19,90 @@
1919
import jakarta.enterprise.inject.Typed;
2020

2121
import java.lang.annotation.Annotation;
22+
import java.util.ArrayList;
2223
import java.util.Arrays;
2324
import java.util.Collection;
2425
import java.util.Collections;
2526
import java.util.HashMap;
2627
import java.util.HashSet;
27-
import java.util.IdentityHashMap;
2828
import java.util.Map;
29+
import java.util.Optional;
2930
import java.util.Set;
31+
import java.util.function.Function;
32+
import java.util.function.Predicate;
33+
import java.util.stream.Stream;
34+
35+
import static io.crysknife.client.internal.QualifierUtil.ANY_ANNOTATION;
36+
import static io.crysknife.client.internal.QualifierUtil.DEFAULT_ANNOTATION;
37+
import static io.crysknife.client.internal.QualifierUtil.DEFAULT_QUALIFIERS;
38+
import static io.crysknife.client.internal.QualifierUtil.SPECIALIZES_ANNOTATION;
39+
import static io.crysknife.client.internal.QualifierUtil.matches;
3040

3141
/**
3242
* @author Dmitrii Tikhomirov Created by treblereel 3/28/19
3343
*/
44+
@SuppressWarnings("unchecked")
3445
public abstract class AbstractBeanManager implements BeanManager {
3546

3647
private final Map<Class, BeanDefinitionHolder> beans = new HashMap<>();
3748

38-
private final Map<Object, BeanFactory> pool = new IdentityHashMap<>();
49+
private final Map<Object, BeanFactory> pool = new HashMap<>();
3950
private final Map<String, Class> beansByBeanName = new HashMap<>();
4051

41-
protected AbstractBeanManager() {
52+
private final Predicate<SyncBeanDefImpl> isTyped =
53+
syncBeanDef -> syncBeanDef.getTyped().isPresent();
54+
private final Predicate<SyncBeanDefImpl> isNotTyped =
55+
syncBeanDef -> syncBeanDef.getTyped().isEmpty();
4256

43-
}
57+
private final Predicate<SyncBeanDefImpl> hasFactory =
58+
syncBeanDef -> syncBeanDef.getFactory().isPresent();
4459

45-
public void register(SyncBeanDefImpl beanDefinition) {
46-
BeanDefinitionHolder holder = get(beanDefinition.getType());
47-
holder.beanDefinition = beanDefinition;
48-
beanDefinition.getAssignableTypes().forEach(superType -> {
49-
get((Class<?>) superType).subTypes.add(holder);
50-
beansByBeanName.put(((Class<?>) superType).getCanonicalName(), (Class<?>) superType);
60+
private final Predicate<SyncBeanDefImpl> hasDefaultQualifiers =
61+
bean -> bean.matches(setOf(DEFAULT_ANNOTATION));
62+
63+
protected AbstractBeanManager() {
5164

52-
});
53-
beansByBeanName.put(beanDefinition.getName(), beanDefinition.getType());
5465
}
5566

56-
private BeanDefinitionHolder get(Class<?> type) {
57-
if (!beans.containsKey(type)) {
58-
BeanDefinitionHolder holder = new BeanDefinitionHolder();
59-
beans.put(type, holder);
67+
public void register(final SyncBeanDefImpl beanDefinition) {
68+
BeanDefinitionHolder holder =
69+
beans.computeIfAbsent(beanDefinition.getType(), k -> new BeanDefinitionHolder());
70+
for (Class<?> superType : (Collection<Class<?>>) beanDefinition.getAssignableTypes()) {
71+
beans.computeIfAbsent(superType, k -> new BeanDefinitionHolder()).subTypes.add(holder);
72+
beansByBeanName.put(superType.getCanonicalName(), superType);
6073
}
61-
return beans.get(type);
74+
Set<Annotation> temp = new HashSet<Annotation>(beanDefinition.getActualQualifiers());
75+
holder.qualifiers.put(temp, beanDefinition);
76+
beansByBeanName.put(beanDefinition.getName(), beanDefinition.getType());
6277
}
6378

6479
@Override
6580
public Collection<SyncBeanDef> lookupBeans(String name) {
6681
if (beansByBeanName.containsKey(name)) {
6782
return lookupBeans(beansByBeanName.get(name));
6883
}
84+
return Collections.EMPTY_SET;
85+
}
6986

87+
public <T> Collection<SyncBeanDef<T>> lookupBeans(final Class<T> type) {
88+
Set<SyncBeanDef<T>> result = new HashSet<>();
89+
if (!beans.containsKey(type)) {
90+
return result;
91+
}
92+
of(beans.get(type)).map(f -> (SyncBeanDef<T>) f).forEach(result::add);
93+
return result;
94+
}
7095

71-
return Collections.EMPTY_SET;
96+
private Stream<SyncBeanDefImpl> of(BeanDefinitionHolder holder,
97+
Predicate<SyncBeanDefImpl>... filters) {
98+
Stream<SyncBeanDefImpl> stream =
99+
Stream.of(holder.subTypes.stream().flatMap(f -> f.qualifiers.values().stream()),
100+
holder.qualifiers.values().stream()).flatMap(Function.identity());
101+
for (Predicate<SyncBeanDefImpl> filter : filters) {
102+
stream = stream.filter(filter);
103+
}
104+
105+
return stream;
72106
}
73107

74108
public <T> Collection<SyncBeanDef<T>> lookupBeans(final Class<T> type, Annotation... qualifiers) {
@@ -78,33 +112,25 @@ public <T> Collection<SyncBeanDef<T>> lookupBeans(final Class<T> type, Annotatio
78112
}
79113

80114
if (qualifiers.length == 0) {
81-
if (beans.get(type).beanDefinition != null) {
82-
result.add(beans.get(type).beanDefinition);
83-
}
84-
beans.get(type).subTypes.stream().filter(f -> f.beanDefinition != null)
85-
.forEach(bean -> result.add(bean.beanDefinition));
86-
return result;
115+
return lookupBeans(type);
87116
}
88117

89-
if (beans.get(type).beanDefinition != null) {
90-
if (compareAnnotations(beans.get(type).beanDefinition.getActualQualifiers(), qualifiers)) {
91-
result.add(beans.get(type).beanDefinition);
92-
}
93-
}
94-
beans.get(type).subTypes.stream().filter(f -> f.beanDefinition != null)
95-
.filter(f -> compareAnnotations(f.beanDefinition.getActualQualifiers(), qualifiers))
96-
.forEach(bean -> result.add(bean.beanDefinition));
118+
of(beans.get(type)).filter(bean -> bean.matches(setOf(qualifiers))).map(f -> (SyncBeanDef<T>) f)
119+
.forEach(result::add);
97120

98121
return result;
99122
}
100123

101-
private boolean compareAnnotations(Collection<Annotation> all, Annotation... in) {
102-
Annotation[] _all = all.toArray(new Annotation[all.size()]);
103-
return QualifierUtil.matches(in, _all);
104-
}
105-
106124
public <T> SyncBeanDef<T> lookupBean(final Class<T> type) {
107-
return lookupBean(type, QualifierUtil.DEFAULT_ANNOTATION);
125+
Collection<IOCBeanDef<T>> candidates = doLookupBean(type, QualifierUtil.DEFAULT_ANNOTATION);
126+
127+
if (candidates.size() > 1) {
128+
throw BeanManagerUtil.ambiguousResolutionException(type, candidates, DEFAULT_ANNOTATION);
129+
} else if (candidates.isEmpty()) {
130+
throw BeanManagerUtil.unsatisfiedResolutionException(type, DEFAULT_ANNOTATION);
131+
} else {
132+
return (SyncBeanDef<T>) candidates.iterator().next();
133+
}
108134
}
109135

110136
public <T> SyncBeanDef<T> lookupBean(final Class<T> type, Annotation... qualifiers) {
@@ -126,110 +152,113 @@ public void destroyBean(Object ref) {
126152
}
127153
}
128154

129-
<T> T addBeanInstanceToPool(Object instance, BeanFactory factory) {
130-
pool.put(instance, factory);
131-
return (T) instance;
132-
}
155+
private <T> Collection<IOCBeanDef<T>> doLookupBean(final Class<T> type,
156+
final Annotation... qualifiers) {
157+
if (!beans.containsKey(type)) {
158+
return Collections.EMPTY_SET;
159+
}
133160

134-
<T> Collection<IOCBeanDef<T>> doLookupBean(final Class<T> type, Annotation... qualifiers) {
135161
Collection<IOCBeanDef<T>> candidates = new HashSet<>();
136-
if (beans.containsKey(type)) {
162+
BeanDefinitionHolder holder = beans.get(type);
137163

138-
if (qualifiers == null || qualifiers.length == 0) {
139-
qualifiers = new Annotation[] {QualifierUtil.DEFAULT_ANNOTATION};
140-
}
164+
Optional<IOCBeanDef<T>> maybeTyped = of(holder, isTyped)
165+
.filter(bean -> Arrays.asList(((Typed) bean.getTyped().get()).value()).contains(type))
166+
.map(bean -> (IOCBeanDef<T>) bean).findFirst();
141167

142-
if (beans.get(type).beanDefinition != null) {
143-
if (beans.get(type).beanDefinition.getTyped().isPresent()) {
144-
if (Arrays.stream(((Typed) beans.get(type).beanDefinition.getTyped().get()).value())
145-
.anyMatch(any -> any.equals(type))) {
146-
Set<IOCBeanDef<T>> result = new HashSet<>();
147-
result.add(beans.get(type).beanDefinition);
148-
return result;
149-
}
150-
}
168+
if (maybeTyped.isPresent()) {
169+
return setOf(maybeTyped.get());
170+
}
151171

152-
if (compareAnnotations(beans.get(type).beanDefinition.getQualifiers(), qualifiers)) {
153-
if (beans.get(type).beanDefinition.getFactory().isPresent()) {
154-
candidates.add(beans.get(type).beanDefinition);
155-
}
156-
}
172+
of(holder, hasFactory, isNotTyped).filter(bean -> {
173+
Set<Annotation> temp = new HashSet<>(bean.getActualQualifiers());
174+
Collections.addAll(temp, DEFAULT_QUALIFIERS);
175+
return compareAnnotations(temp, qualifiers);
176+
}).forEach(bean -> candidates.add((IOCBeanDef<T>) bean));
177+
178+
if (qualifiers.length == 1 && isDefault(qualifiers)) {
179+
Optional<IOCBeanDef<T>> maybeSpecialized =
180+
of(holder, isNotTyped).filter(bean -> bean.matches(setOf(SPECIALIZES_ANNOTATION)))
181+
.map(bean -> (IOCBeanDef<T>) bean).findFirst();
182+
183+
// TODO this is not correct, specialized bean totally overrides the parent bean, including
184+
// qualifiers
185+
if (maybeSpecialized.isPresent()) {
186+
return setOf(maybeSpecialized.get());
157187
}
158188

159-
if (qualifiers.length == 1 && !beans.get(type).subTypes.isEmpty() && isDefault(qualifiers)) {
160-
for (BeanDefinitionHolder subType : beans.get(type).subTypes) {
161-
if (subType.beanDefinition != null) {
162-
if (!subType.beanDefinition.getActualQualifiers().isEmpty()
163-
&& compareAnnotations(subType.beanDefinition.getActualQualifiers(),
164-
QualifierUtil.SPECIALIZES_ANNOTATION)) {
165-
Collection<IOCBeanDef<T>> result = new HashSet<>();
166-
result.add(subType.beanDefinition);
167-
return result;
168-
}
169-
}
170-
}
171-
for (BeanDefinitionHolder subType : beans.get(type).subTypes) {
172-
if (subType.beanDefinition != null) {
173-
if (!subType.beanDefinition.getActualQualifiers().isEmpty() && compareAnnotations(
174-
subType.beanDefinition.getActualQualifiers(), QualifierUtil.DEFAULT_ANNOTATION)) {
175-
Collection<IOCBeanDef<T>> result = new HashSet<>();
176-
result.add(subType.beanDefinition);
177-
return result;
178-
}
179-
}
180-
}
181-
for (BeanDefinitionHolder subType : beans.get(type).subTypes) {
182-
Set<Annotation> annotations = new HashSet<>();
183-
annotations.add(QualifierUtil.DEFAULT_ANNOTATION);
184-
if (compareAnnotations(subType.beanDefinition.getActualQualifiers(), qualifiers)) {
185-
if (subType.beanDefinition.getTyped().isPresent()) {
186-
continue;
187-
} else if (subType.beanDefinition.getFactory().isPresent())
188-
candidates.add(subType.beanDefinition);
189-
}
190-
}
191-
} else {
192-
Set<Annotation> _qual = new HashSet<>();
193-
Collections.addAll(_qual, qualifiers);
194-
Collections.addAll(_qual, QualifierUtil.DEFAULT_QUALIFIERS);
195-
_qual.toArray(new Annotation[_qual.size()]);
196-
197-
for (BeanDefinitionHolder subType : beans.get(type).subTypes) {
198-
if (compareAnnotations(subType.beanDefinition.getQualifiers(),
199-
_qual.toArray(new Annotation[_qual.size()]))) {
200-
if (subType.beanDefinition.getTyped().isPresent()
201-
&& !isDefault(subType.beanDefinition.getActualQualifiers())) {
202-
continue;
203-
} else if (subType.beanDefinition.getFactory().isPresent())
204-
candidates.add(subType.beanDefinition);
205-
}
206-
}
189+
Optional<IOCBeanDef<T>> maybeDefault = of(holder, isNotTyped, hasDefaultQualifiers)
190+
.map(bean -> (IOCBeanDef<T>) bean).findFirst();
191+
192+
if (maybeDefault.isPresent()) {
193+
return setOf(maybeDefault.get());
207194
}
195+
196+
of(holder, isNotTyped, hasFactory, hasDefaultQualifiers).map(bean -> (IOCBeanDef<T>) bean)
197+
.forEach(candidates::add);
198+
} else if (qualifiers.length == 1 && isAny(qualifiers)) {
199+
200+
of(holder, hasFactory)
201+
// .filter(bean -> bean.getTyped().isEmpty()) //TODO not sure about this, may I have to
202+
// filter out @typed beans
203+
.map(bean -> (IOCBeanDef<T>) bean).forEach(candidates::add);
204+
} else {
205+
of(holder, isNotTyped, hasFactory).filter(bean -> bean.matches(setOf(qualifiers)))
206+
.map(bean -> (IOCBeanDef<T>) bean).forEach(candidates::add);
208207
}
209208
return candidates;
210209
}
211210

212-
private boolean isDefault(Collection<Annotation> qualifiers) {
213-
if (qualifiers.isEmpty()) {
214-
return false;
215-
}
216-
return isDefault(qualifiers.toArray(new Annotation[qualifiers.size()]));
211+
private boolean compareAnnotations(Collection<Annotation> all, Annotation... in) {
212+
Annotation[] _all = all.toArray(new Annotation[all.size()]);
213+
return matches(in, _all);
217214
}
218215

219216
private boolean isDefault(Annotation[] qualifiers) {
220217
Annotation[] a1 = new Annotation[] {qualifiers[0]};
221-
Annotation[] a2 = new Annotation[] {QualifierUtil.DEFAULT_ANNOTATION};
222-
return QualifierUtil.matches(a1, a2);
218+
Annotation[] a2 = new Annotation[] {DEFAULT_ANNOTATION};
219+
return matches(a1, a2);
220+
}
221+
222+
private boolean isAny(Annotation[] qualifiers) {
223+
Annotation[] a1 = new Annotation[] {qualifiers[0]};
224+
Annotation[] a2 = new Annotation[] {ANY_ANNOTATION};
225+
return matches(a1, a2);
226+
}
227+
228+
private <T> Collection<IOCBeanDef<T>> doLookupBean(final Class<T> type) {
229+
Collection<IOCBeanDef<T>> candidates = new ArrayList<>();
230+
if (beans.containsKey(type)) {
231+
if (!beans.get(type).qualifiers.isEmpty()) {
232+
beans.get(type).qualifiers.values().forEach(candidates::add);
233+
} else {
234+
of(beans.get(type), isNotTyped, hasFactory).filter(syncBeanDef -> {
235+
if (syncBeanDef.getActualQualifiers().isEmpty()) {
236+
return true;
237+
} else {
238+
return syncBeanDef.matches(setOf(DEFAULT_ANNOTATION));
239+
}
240+
}).map(bean -> (IOCBeanDef<T>) bean).forEach(candidates::add);
241+
}
242+
}
243+
return candidates;
223244
}
224245

225-
private boolean compareAnnotations(Annotation[] all, Annotation[] in) {
226-
return QualifierUtil.matches(in, all);
246+
// replace it with setOf right after we move to Java 11 emulated by J2CL
247+
public static <T> Set<T> setOf(T... values) {
248+
Set<T> set = new HashSet<>();
249+
Collections.addAll(set, values);
250+
return Collections.unmodifiableSet(set);
251+
}
252+
253+
<T> T addBeanInstanceToPool(Object instance, BeanFactory<T> factory) {
254+
pool.put(instance, factory);
255+
return (T) instance;
227256
}
228257

229258
private static class BeanDefinitionHolder {
230259

231-
SyncBeanDefImpl beanDefinition;
232-
Set<BeanDefinitionHolder> subTypes = new HashSet<>();
260+
private final Set<BeanDefinitionHolder> subTypes = new HashSet<>();
261+
private final Map<Set<Annotation>, SyncBeanDefImpl> qualifiers = new HashMap<>();
262+
233263
}
234264
}
235-

core/src/main/java/io/crysknife/client/internal/BeanFactory.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ protected void setIncompleteInstance(final T instance) {
4545
incompleteInstance = instance;
4646
}
4747

48-
public abstract <T> T getInstance();
48+
public abstract T getInstance();
4949

5050
public void initInstance(T instance) {
5151
if (beanDef.getScope().equals(Dependent.class) || !initialized) {
@@ -58,19 +58,19 @@ protected void doInitInstance(T instance) {
5858

5959
}
6060

61-
public <T> T createNewInstance() {
61+
public T createNewInstance() {
6262
if (instance != null) {
6363
createInstance();
6464
}
65-
return (T) instance;
65+
return instance;
6666
}
6767

68-
protected <T> T createInstance() {
68+
protected T createInstance() {
6969
throw new UnsupportedOperationException(
7070
"The factory, " + getClass().getSimpleName() + ", only supports contextual instances.");
7171
}
7272

73-
protected <T> T createInstanceInternal() {
73+
protected T createInstanceInternal() {
7474
T instance = createInstance();
7575
return addBeanInstanceToPool(instance, this);
7676
}
@@ -90,8 +90,8 @@ void onDestroyInternal(T instance) {
9090
initialized = false;
9191
}
9292

93-
protected <T> T addBeanInstanceToPool(Object instance, BeanFactory factory) {
94-
return (T) beanManager.addBeanInstanceToPool(instance, factory);
93+
T addBeanInstanceToPool(T instance, BeanFactory<T> factory) {
94+
return beanManager.addBeanInstanceToPool(instance, factory);
9595
}
9696

9797
}

0 commit comments

Comments
 (0)