1
2
3
4
5
6 package mockit.internal.expectations.state;
7
8 import static mockit.internal.util.Utilities.getClassType;
9
10 import edu.umd.cs.findbugs.annotations.NonNull;
11 import edu.umd.cs.findbugs.annotations.Nullable;
12
13 import java.lang.reflect.Type;
14 import java.util.Iterator;
15 import java.util.Map;
16 import java.util.concurrent.ConcurrentHashMap;
17
18 import mockit.asm.types.JavaType;
19
20 public final class CascadingTypes {
21 @NonNull
22 private final Map<Type, MockedTypeCascade> mockedTypesToCascades;
23
24 CascadingTypes() {
25 mockedTypesToCascades = new ConcurrentHashMap<>(4);
26 }
27
28 public void add(boolean fromMockField, @NonNull Type mockedType) {
29 Class<?> mockedClass = getClassType(mockedType);
30 String mockedTypeDesc = JavaType.getInternalName(mockedClass);
31 add(mockedTypeDesc, fromMockField, mockedType);
32 }
33
34 @NonNull
35 MockedTypeCascade add(@NonNull String mockedTypeDesc, boolean fromMockField, @NonNull Type mockedType) {
36 return mockedTypesToCascades.computeIfAbsent(mockedType,
37 k -> new MockedTypeCascade(fromMockField, mockedType, mockedTypeDesc));
38 }
39
40 @NonNull
41 MockedTypeCascade getCascade(@NonNull Type mockedType) {
42 return mockedTypesToCascades.get(mockedType);
43 }
44
45 @Nullable
46 MockedTypeCascade getCascade(@NonNull String mockedTypeDesc, @Nullable Object mockInstance) {
47 if (mockedTypesToCascades.isEmpty()) {
48 return null;
49 }
50
51 if (mockInstance != null) {
52 MockedTypeCascade cascade = findCascadeForInstance(mockInstance);
53
54 if (cascade != null) {
55 return cascade;
56 }
57 }
58
59 for (MockedTypeCascade cascade : mockedTypesToCascades.values()) {
60 if (cascade.mockedTypeDesc.equals(mockedTypeDesc)) {
61 return cascade;
62 }
63 }
64
65 return null;
66 }
67
68 @Nullable
69 private MockedTypeCascade findCascadeForInstance(@NonNull Object mockInstance) {
70 for (MockedTypeCascade cascade : mockedTypesToCascades.values()) {
71 if (cascade.hasInstance(mockInstance)) {
72 return cascade;
73 }
74 }
75
76 return null;
77 }
78
79 void clearNonSharedCascadingTypes() {
80 if (!mockedTypesToCascades.isEmpty()) {
81 Iterator<MockedTypeCascade> itr = mockedTypesToCascades.values().iterator();
82
83 while (itr.hasNext()) {
84 MockedTypeCascade cascade = itr.next();
85
86 if (cascade.fromMockField) {
87 cascade.discardCascadedMocks();
88 } else {
89 itr.remove();
90 }
91 }
92 }
93 }
94
95 public void clear() {
96 mockedTypesToCascades.clear();
97 }
98
99 void addInstance(@NonNull Type mockedType, @NonNull Object cascadingInstance) {
100 MockedTypeCascade cascade = mockedTypesToCascades.get(mockedType);
101
102 if (cascade != null) {
103 cascade.addInstance(cascadingInstance);
104 }
105 }
106 }