1
2
3
4
5
6 package mockit.internal.expectations;
7
8 import edu.umd.cs.findbugs.annotations.NonNull;
9 import edu.umd.cs.findbugs.annotations.Nullable;
10
11 import java.lang.reflect.Array;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.Collections;
15 import java.util.Iterator;
16 import java.util.LinkedHashSet;
17 import java.util.List;
18 import java.util.Set;
19 import java.util.SortedSet;
20 import java.util.TreeSet;
21
22 final class SequenceOfReturnValues {
23 @NonNull
24 private final Expectation expectation;
25 @NonNull
26 private final Class<?> returnType;
27 @Nullable
28 private final Object firstValue;
29 @NonNull
30 private final Object[] remainingValues;
31
32 SequenceOfReturnValues(@NonNull Expectation expectation, @Nullable Object firstValue,
33 @NonNull Object[] remainingValues) {
34 this.expectation = expectation;
35 returnType = expectation.getReturnType();
36 this.firstValue = firstValue;
37 this.remainingValues = remainingValues;
38 }
39
40 boolean addResultWithSequenceOfValues() {
41 boolean added = false;
42
43 if (returnType != void.class) {
44 if (returnType.isArray()) {
45 added = addValuesInArrayIfApplicable();
46 } else if (Iterator.class.isAssignableFrom(returnType)) {
47 added = addValuesInIteratorIfApplicable();
48 } else if (Iterable.class.isAssignableFrom(returnType)) {
49 added = addValuesInIterableIfApplicable();
50 }
51 }
52
53 return added;
54 }
55
56 private boolean addValuesInArrayIfApplicable() {
57 if (firstValue == null || !firstValue.getClass().isArray()) {
58 addArrayAsReturnValue();
59 return true;
60 }
61
62 return false;
63 }
64
65 private void addArrayAsReturnValue() {
66 Class<?> elementType = returnType.getComponentType();
67 int n = 1 + remainingValues.length;
68 Object values = Array.newInstance(elementType, n);
69 setArrayElement(elementType, values, 0, firstValue);
70
71 for (int i = 1; i < n; i++) {
72 setArrayElement(elementType, values, i, remainingValues[i - 1]);
73 }
74
75 expectation.getResults().addReturnValue(values);
76 }
77
78 private static void setArrayElement(Class<?> elementType, Object array, int index, @Nullable Object value) {
79 Object arrayValue = value;
80
81 if (value != null) {
82 if (elementType == byte.class || elementType == Byte.class) {
83 arrayValue = ((Number) value).byteValue();
84 } else if (elementType == short.class || elementType == Short.class) {
85 arrayValue = ((Number) value).shortValue();
86 }
87 }
88
89 Array.set(array, index, arrayValue);
90 }
91
92 private boolean addValuesInIteratorIfApplicable() {
93 if (firstValue == null || !Iterator.class.isAssignableFrom(firstValue.getClass())) {
94 List<Object> values = new ArrayList<>(1 + remainingValues.length);
95 addAllValues(values);
96 expectation.getResults().addReturnValue(values.iterator());
97 return true;
98 }
99
100 return false;
101 }
102
103 private void addAllValues(@NonNull Collection<Object> values) {
104 values.add(firstValue);
105 Collections.addAll(values, remainingValues);
106 }
107
108 private boolean addValuesInIterableIfApplicable() {
109 if (firstValue == null || !Iterable.class.isAssignableFrom(firstValue.getClass())) {
110 Collection<Object> values;
111
112 if (returnType.isAssignableFrom(List.class)) {
113 values = new ArrayList<>(1 + remainingValues.length);
114 } else if (returnType.isAssignableFrom(Set.class)) {
115 values = new LinkedHashSet<>(1 + remainingValues.length);
116 } else if (returnType.isAssignableFrom(SortedSet.class)) {
117 values = new TreeSet<>();
118 } else {
119 return false;
120 }
121
122 addReturnValues(values);
123 return true;
124 }
125
126 return false;
127 }
128
129 private void addReturnValues(@NonNull Collection<Object> values) {
130 addAllValues(values);
131 expectation.getResults().addReturnValue(values);
132 }
133 }