Skip to content

Commit

Permalink
Add collection support in SizeAnnotationHandler
Browse files Browse the repository at this point in the history
Resolves issue #348
  • Loading branch information
fmbenhassine committed Mar 17, 2019
1 parent eff2ac7 commit 31918c7
Show file tree
Hide file tree
Showing 11 changed files with 304 additions and 334 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,36 +23,136 @@
*/
package org.jeasy.random.validation;

import org.jeasy.random.EasyRandom;
import org.jeasy.random.EasyRandomParameters;
import org.jeasy.random.api.Randomizer;
import org.jeasy.random.randomizers.range.IntegerRangeRandomizer;
import org.jeasy.random.randomizers.text.StringRandomizer;
import org.jeasy.random.util.ReflectionUtils;
import org.objenesis.ObjenesisStd;

import javax.validation.constraints.Size;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.charset.Charset;
import java.util.Random;
import java.util.Collection;
import java.util.EnumMap;
import java.util.Map;

class SizeAnnotationHandler implements BeanValidationAnnotationHandler {
import static org.jeasy.random.util.ReflectionUtils.*;

private final Random random;
class SizeAnnotationHandler implements BeanValidationAnnotationHandler {

private long seed;
private Charset charset;
private EasyRandom easyRandom;

public SizeAnnotationHandler(long seed, Charset charset) {
random = new Random(seed);
SizeAnnotationHandler(long seed, Charset charset) {
this.seed = seed;
this.charset = charset;
}

@Override
@SuppressWarnings({"unchecked"})
public Randomizer<?> getRandomizer(Field field) {
Class<?> fieldType = field.getType();
Size sizeAnnotation = ReflectionUtils
.getAnnotation(field, Size.class);

final int min = sizeAnnotation.min();
final int max = sizeAnnotation.max();
if (easyRandom == null) {
EasyRandomParameters parameters = new EasyRandomParameters()
.seed(this.seed)
.charset(this.charset)
.collectionSizeRange(min, max)
.stringLengthRange(min, max);
easyRandom = new EasyRandom(parameters);
}

if (fieldType.equals(String.class)) {
return new StringRandomizer(charset, min, max, random.nextLong());
return new StringRandomizer(charset, min, max, easyRandom.nextLong());
}

if (isArrayType(fieldType)) {
return (Randomizer<Object>) () -> {
int randomSize = new IntegerRangeRandomizer(min, max, seed).getRandomValue();
Object[] itemsList = (Object[]) Array.newInstance(field.getType().getComponentType(), randomSize);
for (int i = 0; i < randomSize; i++) {
itemsList[i] = (Object) easyRandom.nextObject(fieldType.getComponentType());
}
return itemsList;
};
}

if (isCollectionType(fieldType)) {
return (Randomizer<Object>) () -> {
int randomSize = new IntegerRangeRandomizer(min, max, seed).getRandomValue();
Type fieldGenericType = field.getGenericType();
Collection collection;

if (isInterface(fieldType)) {
collection = getEmptyImplementationForCollectionInterface(fieldType);
} else {
collection = createEmptyCollectionForType(fieldType, randomSize);
}
if (isParameterizedType(fieldGenericType)) {
ParameterizedType parameterizedType = (ParameterizedType) fieldGenericType;
Type type = parameterizedType.getActualTypeArguments()[0];
if (isPopulatable(type)) {
for (int i = 0; i < randomSize; i++) {
Object item = easyRandom.nextObject((Class<?>) type);
collection.add(item);
}

}
}
return collection;
};
}
if (isMapType(fieldType)) {
return (Randomizer<Object>) () -> {
int randomSize = new IntegerRangeRandomizer(min, max, seed).getRandomValue();
Type fieldGenericType = field.getGenericType();
Map<Object, Object> map;

if (isInterface(fieldType)) {
map = (Map<Object, Object>) getEmptyImplementationForMapInterface(fieldType);
} else {
try {
map = (Map<Object, Object>) fieldType.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
if (fieldType.isAssignableFrom(EnumMap.class)) {
if (isParameterizedType(fieldGenericType)) {
Type type = ((ParameterizedType) fieldGenericType).getActualTypeArguments()[0];
map = new EnumMap((Class<?>)type);
} else {
return null;
}
} else {
map = (Map<Object, Object>) new ObjenesisStd().newInstance(fieldType);
}
}
}

if (isParameterizedType(fieldGenericType)) { // populate only parameterized types, raw types will be empty
ParameterizedType parameterizedType = (ParameterizedType) fieldGenericType;
Type keyType = parameterizedType.getActualTypeArguments()[0];
Type valueType = parameterizedType.getActualTypeArguments()[1];
if (isPopulatable(keyType) && isPopulatable(valueType)) {
for (int index = 0; index < randomSize; index++) {
Object randomKey = easyRandom.nextObject((Class<?>) keyType);
Object randomValue = easyRandom.nextObject((Class<?>) valueType);
if(randomKey != null) {
map.put(randomKey, randomValue);
}
}
}
}
return map;
};
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@
*/
package org.jeasy.random.validation;

import lombok.Data;

import javax.validation.constraints.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.*;

@Data
class BeanValidationAnnotatedBean {

@AssertFalse
Expand Down Expand Up @@ -96,224 +99,23 @@ class BeanValidationAnnotatedBean {

@Size(min=2, max=10)
private String briefMessage;

@Pattern(regexp="[a-z]{4}")
private String regexString;

public BeanValidationAnnotatedBean() {
}

public boolean isUnsupported() {
return unsupported;
}

public void setUnsupported(boolean unsupported) {
this.unsupported = unsupported;
}

public boolean isActive() {
return active;
}

public void setActive(boolean active) {
this.active = active;
}

public BigDecimal getMaxDiscount() {
return maxDiscount;
}

public void setMaxDiscount(BigDecimal maxDiscount) {
this.maxDiscount = maxDiscount;
}

public BigDecimal getMinDiscount() {
return minDiscount;
}

public void setMinDiscount(BigDecimal minDiscount) {
this.minDiscount = minDiscount;
}

public Date getEventDate() {
return eventDate;
}

public void setEventDate(Date eventDate) {
this.eventDate = eventDate;
}

public LocalDateTime getEventLocalDateTime() {
return eventLocalDateTime;
}

public Date getFutureOrPresent() {
return futureOrPresent;
}

public Date getBirthday() {
return birthday;
}

public void setBirthday(Date birthday) {
this.birthday = birthday;
}

public LocalDateTime getBirthdayLocalDateTime() {
return birthdayLocalDateTime;
}

public Date getPastOrPresent() {
return pastOrPresent;
}

public int getMaxQuantity() {
return maxQuantity;
}

public void setMaxQuantity(int maxQuantity) {
this.maxQuantity = maxQuantity;
}
@Size(min=2, max=10)
private Collection<String> sizedCollection;

public int getMinQuantity() {
return minQuantity;
}
@Size(min=2, max=10)
private List<String> sizedList;

public void setMinQuantity(int minQuantity) {
this.minQuantity = minQuantity;
}
@Size(min=2, max=10)
private Set<String> sizedSet;

public String getUsername() {
return username;
}
@Size(min=2, max=10)
private Map<String, Integer> sizedMap;

public void setUsername(String username) {
this.username = username;
}
@Size(min=2, max=10)
private String[] sizedArray;

public String getUnusedString() {
return unusedString;
}
@Pattern(regexp="[a-z]{4}")
private String regexString;

public void setUnusedString(String unusedString) {
this.unusedString = unusedString;
}

public String getBriefMessage() {
return briefMessage;
}

public void setBriefMessage(String briefMessage) {
this.briefMessage = briefMessage;
}


public String getRegexString() {
return regexString;
}

public void setRegexString(String regexString) {
this.regexString = regexString;
}

public int getPositive() {
return positive;
}

public void setPositive(int positive) {
this.positive = positive;
}

public int getPositiveOrZero() {
return positiveOrZero;
}

public void setPositiveOrZero(int positiveOrZero) {
this.positiveOrZero = positiveOrZero;
}

public int getNegative() {
return negative;
}

public void setNegative(int negative) {
this.negative = negative;
}

public int getNegativeOrZero() {
return negativeOrZero;
}

public void setNegativeOrZero(int negativeOrZero) {
this.negativeOrZero = negativeOrZero;
}

public String getNotBlank() {
return notBlank;
}

public void setNotBlank(String notBlank) {
this.notBlank = notBlank;
}

public String getEmail() {
return email;
}

public void setEmail(String email) {
this.email = email;
}

public BigDecimal getDiscount() {
return discount;
}

public void setDiscount(BigDecimal discount) {
this.discount = discount;
}

public void setEventLocalDateTime(LocalDateTime eventLocalDateTime) {
this.eventLocalDateTime = eventLocalDateTime;
}

public void setFutureOrPresent(Date futureOrPresent) {
this.futureOrPresent = futureOrPresent;
}

public void setBirthdayLocalDateTime(LocalDateTime birthdayLocalDateTime) {
this.birthdayLocalDateTime = birthdayLocalDateTime;
}

public void setPastOrPresent(Date pastOrPresent) {
this.pastOrPresent = pastOrPresent;
}

@Override
public String toString() {
return "BeanValidationAnnotatedBean{" +
"unsupported=" + unsupported +
", active=" + active +
", maxDiscount=" + maxDiscount +
", minDiscount=" + minDiscount +
", discount=" + discount +
", eventDate=" + eventDate +
", eventLocalDateTime=" + eventLocalDateTime +
", birthday=" + birthday +
", birthdayLocalDateTime=" + birthdayLocalDateTime +
", pastOrPresent=" + pastOrPresent +
", futureOrPresent=" + futureOrPresent +
", maxQuantity=" + maxQuantity +
", minQuantity=" + minQuantity +
", positive=" + positive +
", positiveOrZero=" + positiveOrZero +
", negative=" + negative +
", negativeOrZero=" + negativeOrZero +
", notBlank='" + notBlank + '\'' +
", email='" + email + '\'' +
", username='" + username + '\'' +
", unusedString='" + unusedString + '\'' +
", briefMessage='" + briefMessage + '\'' +
", regexString='" + regexString + '\'' +
'}';
}
}
Loading

0 comments on commit 31918c7

Please sign in to comment.