<commit_before>/*
 * Copyright © 2015 Bobulous <http://www.bobulous.org.uk/>.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 * obtain one at http://mozilla.org/MPL/2.0/.
 */
package uk.org.bobulous.java.intervals;

import java.util.Objects;

/**
 * An immutable <code>NumericInterval</code> whose endpoints have type
 * <code>Integer</code>.
 *
 * <p>
 * <strong>WARNING:</strong> development and testing are still in early stages.
 * Consider this class to be in its alpha testing phase. Use with caution, and
 * do not rely on its structure remaining in exactly its current form!</p>
 *
 * @author Bobulous <http://www.bobulous.org.uk/>
 */
public class IntegerInterval implements NumericInterval<Integer> {

	private final Integer lower;
	private final Integer upper;

	private final EndpointMode lowerMode;
	private final EndpointMode upperMode;

	/**
	 * An interval which permits no values: the empty set. Note that the
	 * endpoint values are arbitrary and that any <code>IntegerInterval</code>
	 * which is empty is considered equal to this instance of the empty set.
	 */
	public static final IntegerInterval EMPTY_SET = new IntegerInterval(
			EndpointMode.OPEN, 0, 0, EndpointMode.OPEN);

	/*
	Private constructor because static methods are provided for the creation of
	intervals with different endpoint modes. (This also allows for the option of
	adding caching of common instances in future.)
	*/
	private IntegerInterval(EndpointMode lowerMode, Integer lower, Integer upper,
			EndpointMode upperMode) {
		this.lower = lower;
		this.upper = upper;
		this.lowerMode = lowerMode;
		this.upperMode = upperMode;
	}

	/**
	 * Constructs a closed interval with the given integer endpoint values.
	 *
	 * @param lower the value of the lower endpoint or <code>null</code> if the
	 * lower endpoint is unbounded (infinite).
	 * @param upper the value of the upper endpoint or <code>null</code> if the
	 * upper endpoint is unbounded (infinite).
	 * @return an <code>IntegerInterval</code> with the given endpoint values
	 * and both endpoint modes set to <code>EndpointMode.CLOSED</code>.
	 */
	public static IntegerInterval closed(Integer lower, Integer upper) {
		return new IntegerInterval(EndpointMode.CLOSED, lower, upper,
				EndpointMode.CLOSED);
	}

	/**
	 * Constructs an open interval with the given integer endpoint values.
	 *
	 * @param lower the value of the lower endpoint or <code>null</code> if the
	 * lower endpoint is unbounded (infinite).
	 * @param upper the value of the upper endpoint or <code>null</code> if the
	 * upper endpoint is unbounded (infinite).
	 * @return an <code>IntegerInterval</code> with the given endpoint values
	 * and both endpoint modes set to <code>EndpointMode.OPEN</code>.
	 */
	public static IntegerInterval open(Integer lower, Integer upper) {
		return new IntegerInterval(EndpointMode.OPEN, lower, upper,
				EndpointMode.OPEN);
	}

	/**
	 * Constructs a left-closed interval with the given integer endpoint values.
	 *
	 * @param lower the value of the lower endpoint or <code>null</code> if the
	 * lower endpoint is unbounded (infinite).
	 * @param upper the value of the upper endpoint or <code>null</code> if the
	 * upper endpoint is unbounded (infinite).
	 * @return an <code>IntegerInterval</code> with the given endpoint values
	 * and the lower endpoint mode set to <code>EndpointMode.CLOSED</code> and
	 * the upper endpoint mode set to <code>EndpointMode.OPEN</code>.
	 */
	public static IntegerInterval leftClosed(Integer lower, Integer upper) {
		return new IntegerInterval(EndpointMode.CLOSED, lower, upper,
				EndpointMode.OPEN);
	}

	/**
	 * Constructs a right-closed interval with the given integer endpoint
	 * values.
	 *
	 * @param lower the value of the lower endpoint or <code>null</code> if the
	 * lower endpoint is unbounded (infinite).
	 * @param upper the value of the upper endpoint or <code>null</code> if the
	 * upper endpoint is unbounded (infinite).
	 * @return an <code>IntegerInterval</code> with the given endpoint values
	 * and the lower endpoint mode set to <code>EndpointMode.OPEN</code> and the
	 * upper endpoint mode set to <code>EndpointMode.CLOSED</code>.
	 */
	public static IntegerInterval rightClosed(Integer lower, Integer upper) {
		return new IntegerInterval(EndpointMode.OPEN, lower, upper,
				EndpointMode.CLOSED);
	}

	@Override
	public Integer width() {
		if (this.isEmpty()) {
			return 0;
		}
		if (upper == null || lower == null) {
			return null;
		}
		return upper - lower;
	}

	@Override
	public boolean isEmpty() {
		if (upper == null || lower == null) {
			// Unbounded intervals are never empty.<commit_msg>Marked IntegerInterval class as final, and marked the static factory methods as final. Added common integer intervals as public static final class fields.<commit_after>/*
 * Copyright © 2015 Bobulous <http://www.bobulous.org.uk/>.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public License,
 * v. 2.0. If a copy of the MPL was not distributed with this file, You can
 * obtain one at http://mozilla.org/MPL/2.0/.
 */
package uk.org.bobulous.java.intervals;

import java.util.Objects;

/**
 * An immutable <code>NumericInterval</code> whose endpoints have type
 * <code>Integer</code>.
 *
 * <p>
 * <strong>WARNING:</strong> development and testing are still in early stages.
 * Consider this class to be in its alpha testing phase. Use with caution, and
 * do not rely on its structure remaining in exactly its current form!</p>
 *
 * @author Bobulous <http://www.bobulous.org.uk/>
 */
public final class IntegerInterval implements NumericInterval<Integer> {

	private final Integer lower;
	private final Integer upper;

	private final EndpointMode lowerMode;
	private final EndpointMode upperMode;

	/**
	 * An interval which permits no values: the empty set. Note that the
	 * endpoint values are arbitrary and that any <code>IntegerInterval</code>
	 * which is empty is considered equal to this instance of the empty set.
	 */
	public static final IntegerInterval EMPTY_SET = new IntegerInterval(
			EndpointMode.OPEN, 0, 0, EndpointMode.OPEN);

	/**
	 * An interval which includes all <code>Integer</code> values.
	 */
	public static final IntegerInterval UNBOUNDED = new IntegerInterval(
			EndpointMode.OPEN, null, null, EndpointMode.OPEN);

	/**
	 * An interval which includes only the integers zero and one.
	 */
	public static final IntegerInterval ZERO_OR_ONE = new IntegerInterval(
			EndpointMode.CLOSED, 0, 1, EndpointMode.CLOSED);

	/**
	 * An interval which includes all non-negative <code>Integer</code> values.
	 * Any <code>Integer</code> value greater-than-or-equal-to zero is included.
	 */
	public static final IntegerInterval ZERO_OR_MORE = new IntegerInterval(
			EndpointMode.CLOSED, 0, null, EndpointMode.OPEN);

	/**
	 * An interval which includes all positive, non-zero <code>Integer</code>
	 * values. Any <code>Integer</code> value greater-than-or-equal-to one is
	 * included.
	 */
	public static final IntegerInterval ONE_OR_MORE = new IntegerInterval(
			EndpointMode.CLOSED, 1, null, EndpointMode.OPEN);

	/*
	Private constructor because static methods are provided for the creation of
	intervals with different endpoint modes. (This also allows for the option of
	adding caching of common instances in future.)
	*/
	private IntegerInterval(EndpointMode lowerMode, Integer lower, Integer upper,
			EndpointMode upperMode) {
		this.lower = lower;
		this.upper = upper;
		this.lowerMode = lowerMode;
		this.upperMode = upperMode;
	}

	/**
	 * Constructs a closed interval with the given integer endpoint values.
	 *
	 * @param lower the value of the lower endpoint or <code>null</code> if the
	 * lower endpoint is unbounded (infinite).
	 * @param upper the value of the upper endpoint or <code>null</code> if the
	 * upper endpoint is unbounded (infinite).
	 * @return an <code>IntegerInterval</code> with the given endpoint values
	 * and both endpoint modes set to <code>EndpointMode.CLOSED</code>.
	 */
	public static final IntegerInterval closed(Integer lower, Integer upper) {
		return new IntegerInterval(EndpointMode.CLOSED, lower, upper,
				EndpointMode.CLOSED);
	}

	/**
	 * Constructs an open interval with the given integer endpoint values.
	 *
	 * @param lower the value of the lower endpoint or <code>null</code> if the
	 * lower endpoint is unbounded (infinite).
	 * @param upper the value of the upper endpoint or <code>null</code> if the
	 * upper endpoint is unbounded (infinite).
	 * @return an <code>IntegerInterval</code> with the given endpoint values
	 * and both endpoint modes set to <code>EndpointMode.OPEN</code>.
	 */
	public static final IntegerInterval open(Integer lower, Integer upper) {
		return new IntegerInterval(EndpointMode.OPEN, lower, upper,
				EndpointMode.OPEN);
	}

	/**
	 * Constructs a left-closed interval with the given integer endpoint values.
	 *
	 * @param lower the value of the lower endpoint or <code>null</code> if the
	 * lower endpoint is unbounded (infinite).
	 * @param upper the value of the upper endpoint or <code>null</code> if the
	 * upper endpoint is unbounded (infinite).
	 * @return an <code>IntegerInterval</code> with the given endpoint values
	 * and the lower endpoint mode set to <code>EndpointMode.CLOSED</code> and
	 * the upper endpoint mode set to <code>EndpointMode.OPEN</code>.
	 */
	public static final IntegerInterval leftClosed(Integer lower, Integer upper) {
		return new IntegerInterval(EndpointMode.CLOSED, lower, upper,
				EndpointMode.OPEN);
	}

	/**
	 * Constructs a right-closed interval with the given integer endpoint
	 * values.
	 *
	 * @param lower the value of the lower endpoint or <code>null</code> if the
	 * lower endpoint is unbounded (infinite).
	 * @param upper the value of the upper endpoint or <code>null</code> if the
	 * upper endpoint is unbounded (infinite).
	 * @return an <code>IntegerInterval</code> with the given endpoint values
	 * and the lower endpoint mode set to <code>EndpointMode.OPEN</code> and the
	 * upper endpoint mode set to <code>EndpointMode.CLOSED</code>.
	 */
	public static final IntegerInterval rightClosed(Integer lower, Integer upper) {
		return new IntegerInterval(EndpointMode.OPEN, lower, upper,
				EndpointMode.CLOSED);
	}

	@Override
	public Integer width() {
		if (this.isEmpty()) {
			return 0;
		}
		if (upper == null || lower == null) {
			return null;
		}
		return upper - lower;
	}

	@Override
	public boolean isEmpty() {
		if (upper == null || lower == null) {
			// Unbounded intervals are never empty.
{'fraction_non_alphanumeric': 0.09369132557266241, 'fraction_numerical': 0.00244085617724371, 'mean_word_length': 3.9641192917054986, 'pattern_counts': {'":': 0, '<': 111, '<?xml version=': 0, '>': 111, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4551691', 'n_tokens_mistral': 3114, 'n_tokens_neox': 2848, 'n_words': 1200}