package com.flextrade.jfixture.builders;
import com.flextrade.jfixture.NoSpecimen;
import com.flextrade.jfixture.SpecimenBuilder;
import com.flextrade.jfixture.SpecimenContext;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Random;
public class NumberInRangeGenerator implements SpecimenBuilder {
private final long[] limits;
private final HashSet<Long> numbers;
private long lower;
private long upper;
private long count;
private final Random random;
public NumberInRangeGenerator() {
this(1, Byte.MAX_VALUE, Short.MAX_VALUE, Integer.MAX_VALUE);
}
public NumberInRangeGenerator(long... limits) {
this.limits = limits;
this.numbers = new HashSet<Long>();
this.random = new Random();
this.createRange();
}
@Override
public Object create(Object request, SpecimenContext context) {
if (request.equals(Byte.class)) {
return (byte) getNextRandom();
} else if (request.equals(Short.class)) {
return (short) getNextRandom();
} else if (request.equals(Integer.class)) {
return (int) getNextRandom();
} else if (request.equals(Long.class)) {
return getNextRandom();
} else if (request.equals(Float.class)) {
return (float) getNextRandom();
} else if (request.equals(Double.class)) {
return (double) getNextRandom();
} else if (request.equals(BigDecimal.class)) {
return BigDecimal.valueOf(getNextRandom());
} else if (request.equals(BigInteger.class)) {
return BigInteger.valueOf(getNextRandom());
}
return new NoSpecimen();
}
private long getNextRandom() {
this.evaluateRange();
long result;
do {
result = (long)(this.random.nextDouble() * (this.upper - this.lower)) + this.lower;
}
while (this.numbers.contains(result));
this.numbers.add(result);
return result;
}
private void evaluateRange() {
if (this.count == (this.upper - this.lower)) {
this.count = 0;
this.createRange();
}
this.count++;
}
private void createRange() {
List<Long> remaining = getRemainingValues();
if (remaining.size() > 0 && this.numbers.size() > 0) {
this.lower = this.upper;
this.upper = Collections.min(remaining) + 1;
} else {
this.lower = limits[0];
this.upper = limits[1];
}
this.numbers.clear();
}
private List<Long> getRemainingValues() {
List<Long> remaining = new ArrayList<Long>();
for (long l : this.limits) {
if (l > this.upper - 1) remaining.add(l);
}
return remaining;
}
}