Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import com.navercorp.fixturemonkey.api.exception.RetryableFilterMissException;
import com.navercorp.fixturemonkey.api.lazy.LazyArbitrary;
import com.navercorp.fixturemonkey.api.validator.ValidationFailureRecorder;

/**
* An arbitrary instance for combining arbitraries in order to generate an instance of specific class.
Expand Down Expand Up @@ -160,6 +161,27 @@ default CombinableArbitrary<T> filter(int tries, Predicate<T> predicate) {
);
}

default CombinableArbitrary<T> filter(
int tries,
Predicate<T> predicate,
ValidationFailureRecorder validationFailureRecorder
) {
if (this instanceof FilteredCombinableArbitrary) {
return new FilteredCombinableArbitrary<>(
tries,
(FilteredCombinableArbitrary<T>)this,
predicate,
validationFailureRecorder
);
}
return new FilteredCombinableArbitrary<>(
tries,
this,
predicate,
validationFailureRecorder
);
}

/**
* Transforms a generated object into a new object.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.navercorp.fixturemonkey.api.exception.ValidationFailedException;
import com.navercorp.fixturemonkey.api.property.PropertyPath;
import com.navercorp.fixturemonkey.api.property.Traceable;
import com.navercorp.fixturemonkey.api.validator.ValidationFailureRecorder;

/**
* It would generate an object satisfied given {@code predicate}.
Expand All @@ -41,27 +42,51 @@ final class FilteredCombinableArbitrary<T> implements CombinableArbitrary<T> {
private final int maxMisses;
private final CombinableArbitrary<T> combinableArbitrary;
private final Predicate<T> predicate;
@Nullable
private final ValidationFailureRecorder validationFailureRecorder;

private Exception lastException;

FilteredCombinableArbitrary(
int maxMisses,
CombinableArbitrary<T> combinableArbitrary,
Predicate<T> predicate
) {
this(maxMisses, combinableArbitrary, predicate, null);
}

FilteredCombinableArbitrary(
int maxMisses,
FilteredCombinableArbitrary<T> filteredCombinableArbitrary,
Predicate<T> predicate
) {
this(maxMisses, filteredCombinableArbitrary, predicate, null);
}

FilteredCombinableArbitrary(
int maxMisses,
CombinableArbitrary<T> combinableArbitrary,
Predicate<T> predicate,
@Nullable ValidationFailureRecorder validationFailureRecorder
) {
this.maxMisses = maxMisses;
this.combinableArbitrary = combinableArbitrary;
this.predicate = predicate;
this.validationFailureRecorder = validationFailureRecorder;
}

FilteredCombinableArbitrary(
int maxMisses,
FilteredCombinableArbitrary<T> filteredCombinableArbitrary,
Predicate<T> predicate
Predicate<T> predicate,
@Nullable ValidationFailureRecorder validationFailureRecorder
) {
this.maxMisses = maxMisses;
this.combinableArbitrary = filteredCombinableArbitrary.combinableArbitrary;
this.predicate = predicate.and(filteredCombinableArbitrary.predicate);
this.validationFailureRecorder = validationFailureRecorder != null
? validationFailureRecorder
: filteredCombinableArbitrary.validationFailureRecorder;
}

@Override
Expand All @@ -74,6 +99,8 @@ public T combined() {
return returned;
}

throwIfValidationFailed();

if (fixed()) {
throw new FixedValueFilterMissException("Fixed value can not satisfy given filter.");
}
Expand All @@ -82,45 +109,18 @@ public T combined() {
lastException = ex;
}
combinableArbitrary.clear();
if (ex instanceof ValidationFailedException
|| (ex.getCause() instanceof ValidationFailedException)) {
break;
}
}
}

if (lastException == null && combinableArbitrary instanceof FilteredCombinableArbitrary) {
lastException = ((FilteredCombinableArbitrary<T>)combinableArbitrary).lastException;
}

if (lastException instanceof ValidationFailedException) {
String failedConcatProperties = String.join(", ",
((ValidationFailedException)lastException).getConstraintViolationPropertyNames());

throw new RetryableFilterMissException(
String.format("Given properties \"%s\" is not validated by annotations.", failedConcatProperties),
lastException
);
}

if (lastException != null) {
throw newRetryableFilterMissException(lastException);
}

if (combinableArbitrary instanceof Traceable) {
PropertyPath propertyPath = ((Traceable)combinableArbitrary).getPropertyPath();
String generateType = propertyPath.getProperty().getType().getTypeName();
String expression = "".equals(propertyPath.getExpression())
? "$"
: propertyPath.getExpression();

throw new RetryableFilterMissException(
String.format(
"Generate type \"%s\" is failed due to property \"%s\".",
generateType,
expression
),
lastException
);
}

throw newRetryableFilterMissException(lastException);
return throwLastException();
}

@SuppressWarnings({"unchecked", "override.return", "argument"})
Expand All @@ -134,6 +134,8 @@ public T rawValue() {
return returned;
}

throwIfValidationFailed();

if (fixed()) {
throw new FixedValueFilterMissException("Fixed value can not satisfy given filter.");
}
Expand All @@ -142,6 +144,10 @@ public T rawValue() {
lastException = ex;
}
combinableArbitrary.clear();
if (ex instanceof ValidationFailedException
|| (ex.getCause() instanceof ValidationFailedException)) {
break;
}
} catch (ClassCastException ex) {
throw new ClassCastException(
String.format(
Expand All @@ -156,6 +162,10 @@ public T rawValue() {
lastException = ((FilteredCombinableArbitrary<T>)combinableArbitrary).lastException;
}

return throwLastException();
}

private T throwLastException() {
if (lastException instanceof ValidationFailedException) {
String failedConcatProperties = String.join(", ",
((ValidationFailedException)lastException).getConstraintViolationPropertyNames());
Expand Down Expand Up @@ -213,4 +223,14 @@ private RetryableFilterMissException newRetryableFilterMissException(@Nullable T

return (RetryableFilterMissException)throwable;
}

private void throwIfValidationFailed() {
if (validationFailureRecorder == null) {
return;
}

validationFailureRecorder.consume().ifPresent(ex -> {
throw ex;
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ public final class JavaStringConstraint {

private final boolean notBlank;

private final boolean notEmpty;

@Nullable
private final PatternConstraint pattern;

Expand All @@ -49,6 +51,7 @@ public JavaStringConstraint(
boolean digits,
boolean notNull,
boolean notBlank,
boolean notEmpty,
@Nullable PatternConstraint pattern,
boolean email
) {
Expand All @@ -57,6 +60,7 @@ public JavaStringConstraint(
this.digits = digits;
this.notNull = notNull;
this.notBlank = notBlank;
this.notEmpty = notEmpty;
this.pattern = pattern;
this.email = email;
}
Expand All @@ -83,6 +87,10 @@ public boolean isNotBlank() {
return this.notBlank;
}

public boolean isNotEmpty() {
return this.notEmpty;
}

@Nullable
public PatternConstraint getPattern() {
return pattern;
Expand Down
Loading
Loading