All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.jqwik.engine.properties.shrinking.CombinedShrinkable Maven / Gradle / Ivy

The newest version!
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 CombinedShrinkable implements Shrinkable {
	private final List> parts;
	private final Function, ? extends T> combinator;

	public CombinedShrinkable(List> parts, Function, ? extends T> combinator) {
		this.parts = parts;
		this.combinator = combinator;
	}

	@Override
	public T value() {
		return createValue(parts);
	}

	private T createValue(List> shrinkables) {
		return combinator.apply(createValues(shrinkables));
	}

	private List createValues(List> shrinkables) {
		// Using loop instead of stream to make stack traces more readable
		List values = new ArrayList<>();
		for (Shrinkable shrinkable : shrinkables) {
			values.add(shrinkable.value());
		}
		return values;
	}

	@Override
	public Stream> shrink() {
		return shrinkPartsOneAfterTheOther();
	}

	protected Stream> shrinkPartsOneAfterTheOther() {
		List>> shrinkPerPartStreams = new ArrayList<>();
		for (int i = 0; i < parts.size(); i++) {
			int index = i;
			Shrinkable part = parts.get(i);
			Stream> shrinkElement = part.shrink().flatMap(shrunkElement -> {
				List> partsCopy = new ArrayList<>(parts);
				partsCopy.set(index, shrunkElement);
				return Stream.of(new CombinedShrinkable<>(partsCopy, combinator));
			});
			shrinkPerPartStreams.add(shrinkElement);
		}
		return JqwikStreamSupport.concat(shrinkPerPartStreams);
	}

	@Override
	public ShrinkingDistance distance() {
		return ShrinkingDistance.combine(parts);
	}

}