/*
* Copyright (c) 2006-2012 Rogério Liesenfeld
* This file is subject to the terms of the MIT license (see LICENSE.txt).
*/
package mockit.internal.expectations;
import java.lang.reflect.*;
import java.util.*;
final class SequenceOfReturnValues
{
private final Expectation expectation;
private final Class<?> returnType;
private final Object firstValue;
private final Object[] remainingValues;
SequenceOfReturnValues(Expectation expectation, Object firstValue, Object[] remainingValues)
{
this.expectation = expectation;
returnType = expectation.getReturnType();
this.firstValue = firstValue;
this.remainingValues = remainingValues;
}
boolean addResultWithSequenceOfValues()
{
boolean added = false;
if (returnType != void.class) {
if (returnType.isArray()) {
added = addValuesInArrayIfApplicable();
}
else if (Iterator.class.isAssignableFrom(returnType)) {
added = addValuesInIteratorIfApplicable();
}
else if (Iterable.class.isAssignableFrom(returnType)) {
added = addValuesInIterableIfApplicable();
}
}
return added;
}
private boolean addValuesInArrayIfApplicable()
{
if (firstValue == null || !firstValue.getClass().isArray()) {
addArrayAsReturnValue();
return true;
}
return false;
}
private void addArrayAsReturnValue()
{
Class<?> elementType = returnType.getComponentType();
int n = 1 + remainingValues.length;
Object values = Array.newInstance(elementType, n);
setArrayElement(elementType, values, 0, firstValue);
for (int i = 1; i < n; i++) {
setArrayElement(elementType, values, i, remainingValues[i - 1]);
}
expectation.getResults().addReturnValue(values);
}
@SuppressWarnings("AssignmentToMethodParameter")
private void setArrayElement(Class<?> elementType, Object array, int index, Object value)
{
if (elementType == byte.class || elementType == Byte.class) {
value = ((Number) value).byteValue();
}
else if (elementType == short.class || elementType == Short.class) {
value = ((Number) value).shortValue();
}
Array.set(array, index, value);
}
private boolean addValuesInIteratorIfApplicable()
{
if (firstValue == null || !Iterator.class.isAssignableFrom(firstValue.getClass())) {
List<Object> values = new ArrayList<Object>(1 + remainingValues.length);
addAllValues(values);
expectation.getResults().addReturnValue(values.iterator());
return true;
}
return false;
}
private void addAllValues(Collection<Object> values)
{
values.add(firstValue);
Collections.addAll(values, remainingValues);
}
private boolean addValuesInIterableIfApplicable()
{
if (firstValue == null || !Iterable.class.isAssignableFrom(firstValue.getClass())) {
if (returnType.isAssignableFrom(List.class)) {
List<Object> values = new ArrayList<Object>(1 + remainingValues.length);
addReturnValues(values);
return true;
}
else if (returnType.isAssignableFrom(Set.class)) {
Set<Object> values = new LinkedHashSet<Object>(1 + remainingValues.length);
addReturnValues(values);
return true;
}
else if (returnType.isAssignableFrom(SortedSet.class)) {
addReturnValues(new TreeSet<Object>());
return true;
}
}
return false;
}
private void addReturnValues(Collection<Object> values)
{
addAllValues(values);
expectation.getResults().addReturnValue(values);
}
}