net.jqwik.engine.properties.shrinking.CollectShrinkable Maven / Gradle / Ivy
package net.jqwik.engine.properties.shrinking;
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
import net.jqwik.api.*;
import net.jqwik.engine.support.*;
import org.jspecify.annotations.*;
public class CollectShrinkable implements Shrinkable> {
private final List extends Shrinkable> elements;
private final Predicate super List extends T>> until;
public CollectShrinkable(List extends Shrinkable> elements, Predicate super List extends T>> until) {
this.elements = elements;
this.until = until;
}
@Override
public List value() {
return createValue(elements);
}
private List createValue(List extends Shrinkable> elements) {
return elements
.stream()
.map(Shrinkable::value)
.collect(Collectors.toList());
}
@Override
public Stream>> shrink() {
return JqwikStreamSupport.concat(
shrinkElementsOneAfterTheOther(),
sortElements()
).filter(s -> until.test(s.value()));
}
private Stream>> shrinkElementsOneAfterTheOther() {
List>>> shrinkPerPartStreams = new ArrayList<>();
for (int i = 0; i < elements.size(); i++) {
int index = i;
Shrinkable part = elements.get(i);
Stream>> shrinkElement = part.shrink().flatMap(shrunkElement -> {
Optional>> shrunkCollection = collectElements(index, shrunkElement);
return shrunkCollection
.map(shrunkElements -> Stream.of(createShrinkable(shrunkElements)))
.orElse(Stream.empty());
});
shrinkPerPartStreams.add(shrinkElement);
}
return JqwikStreamSupport.concat(shrinkPerPartStreams);
}
private Stream>> sortElements() {
return ShrinkingCommons.sortElements(elements, (ShrinkingCommons.ContainerCreator, T>) this::createShrinkable);
}
private CollectShrinkable createShrinkable(List extends Shrinkable> pairSwap) {
return new CollectShrinkable<>(pairSwap, until);
}
private Optional>> collectElements(int replaceIndex, Shrinkable shrunkElement) {
List> newElements = new ArrayList<>();
for (int i = 0; i < elements.size(); i++) {
if (i == replaceIndex) {
newElements.add(shrunkElement);
} else {
newElements.add(elements.get(i));
}
if (until.test(createValue(newElements))) {
return Optional.of(newElements);
}
}
return Optional.empty();
}
@Override
public ShrinkingDistance distance() {
return ShrinkingDistance.forCollection(elements);
}
}