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

org.junitpioneer.jupiter.params.Range Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016-2023 the original author or authors.
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v2.0 which
 * accompanies this distribution and is available at
 *
 * http://www.eclipse.org/legal/epl-v20.html
 */

package org.junitpioneer.jupiter.params;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * An iterator for numerical ranges, used as the backing logic for {@link RangeSourceArgumentsProvider}.
 * @param  The numerical type used by the range.
 */
abstract class Range> implements Iterator {

	private final N from;
	private final N to;
	private final N step;
	private final boolean closed;
	private N current;
	private final int sign;
	private final N zero;

	Range(N from, N to, N step, boolean closed, N zero) {
		this.from = from;
		this.to = to;
		this.step = step;
		this.closed = closed;
		this.zero = zero;
		current = null;
		sign = step.compareTo(getZero());
	}

	/**
	 * Asserts the range is valid.
	 * @throws IllegalArgumentException if the range is not valid
	 */
	void validate() {
		if (step.equals(getZero())) {
			throw new IllegalArgumentException("Illegal range. The step cannot be zero.");
		}

		if (!closed && from.equals(to)) {
			throw new IllegalArgumentException("Illegal range. Equal from and to will produce an empty range.");
		}

		boolean fromNotEqualsTo = (from.compareTo(to) != 0);

		if ((isValidDescending()) && (!closed || fromNotEqualsTo)) {
			String message = String
					.format("Illegal range. There's no way to get from %s to %s with a step of %s.", from, to, step);
			throw new IllegalArgumentException(message);
		}
	}

	boolean isValidDescending() {
		boolean fromIsLessThanTo = (from.compareTo(to) < 0);
		boolean stepIsLessThanZero = (sign < 0);

		return fromIsLessThanTo == stepIsLessThanZero;
	}

	N getStep() {
		return step;
	}

	N getCurrent() {
		return current;
	}

	/**
	 * The next value in the range. Calling {@link #next()} will return this value and advance the iterator to it.
	 */
	abstract N nextValue();

	private N getNextValue() {
		if (current == null) {
			return from;
		}
		return nextValue();
	}

	/**
	 * The value of the no-op "zero", illegal step in terms of N
	 */
	private N getZero() {
		return zero;
	}

	@Override
	public boolean hasNext() {
		if (current == null) {
			return true;
		}
		N nextValue = getNextValue();
		int cmp = nextValue.compareTo(to);
		int overflowCheck = nextValue.compareTo(current);
		return ((cmp < 0 != sign < 0) && (overflowCheck < 0 == sign < 0)) || (closed && cmp == 0);
	}

	@Override
	public N next() {
		if (!hasNext()) {
			throw new NoSuchElementException();
		}
		current = getNextValue();
		return current;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy