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