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

com.io7m.jaffirm.core.Preconditions Maven / Gradle / Ivy

/*
 * Copyright © 2016 Mark Raynsford  https://www.io7m.com
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

package com.io7m.jaffirm.core;

import com.io7m.junreachable.UnreachableCodeException;

import java.util.function.DoubleFunction;
import java.util.function.DoublePredicate;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.IntPredicate;
import java.util.function.LongFunction;
import java.util.function.LongPredicate;
import java.util.function.Predicate;
import java.util.function.Supplier;

import static com.io7m.jaffirm.core.SafeApplication.applyDescriberChecked;
import static com.io7m.jaffirm.core.SafeApplication.applyDescriberDChecked;
import static com.io7m.jaffirm.core.SafeApplication.applyDescriberIChecked;
import static com.io7m.jaffirm.core.SafeApplication.applyDescriberLChecked;
import static com.io7m.jaffirm.core.SafeApplication.applySupplierChecked;
import static com.io7m.jaffirm.core.SafeApplication.failedPredicate;
import static com.io7m.jaffirm.core.Violations.innerCheckAll;
import static com.io7m.jaffirm.core.Violations.innerCheckAllDouble;
import static com.io7m.jaffirm.core.Violations.innerCheckAllInt;
import static com.io7m.jaffirm.core.Violations.innerCheckAllLong;
import static com.io7m.jaffirm.core.Violations.singleViolation;

/**
 * Functions to check preconditions.
 */

public final class Preconditions
{
  private Preconditions()
  {
    throw new UnreachableCodeException();
  }

  /**
   * 

Evaluate all of the given {@code conditions} using {@code value} as * input.

* *

All of the conditions are evaluated and the function throws {@link * PreconditionViolationException} if any of the conditions are false, or * raise an exception that is not of type {@link Error}. Exceptions of type * {@link Error} are propagated immediately, without any further contract * checking.

* * @param value The value * @param conditions The set of conditions * @param The type of values * * @return value * * @throws PreconditionViolationException If any of the conditions are false */ @SafeVarargs public static T checkPreconditions( final T value, final ContractConditionType... conditions) throws PreconditionViolationException { final Violations violations = innerCheckAll(value, conditions); if (violations != null) { throw new PreconditionViolationException( failedMessage(value, violations), null, violations.count()); } return value; } /** * An {@code int} specialized version of {@link #checkPreconditions(Object, * ContractConditionType[])} * * @param value The value * @param conditions The conditions the value must obey * * @return value * * @throws PreconditionViolationException If any of the conditions are false */ public static int checkPreconditionsI( final int value, final ContractIntConditionType... conditions) throws PreconditionViolationException { final Violations violations = innerCheckAllInt(value, conditions); if (violations != null) { throw new PreconditionViolationException( failedMessage(Integer.valueOf(value), violations), null, violations.count()); } return value; } /** * A {@code long} specialized version of {@link #checkPreconditions(Object, * ContractConditionType[])} * * @param value The value * @param conditions The conditions the value must obey * * @return value * * @throws PreconditionViolationException If any of the conditions are false */ public static long checkPreconditionsL( final long value, final ContractLongConditionType... conditions) throws PreconditionViolationException { final Violations violations = innerCheckAllLong(value, conditions); if (violations != null) { throw new PreconditionViolationException( failedMessage(Long.valueOf(value), violations), null, violations.count()); } return value; } /** * A {@code double} specialized version of {@link #checkPreconditions(Object, * ContractConditionType[])} * * @param value The value * @param conditions The conditions the value must obey * * @return value * * @throws PreconditionViolationException If any of the conditions are false */ public static double checkPreconditionsD( final double value, final ContractDoubleConditionType... conditions) throws PreconditionViolationException { final Violations violations = innerCheckAllDouble(value, conditions); if (violations != null) { throw new PreconditionViolationException( failedMessage(Double.valueOf(value), violations), null, violations.count()); } return value; } /** *

Evaluate the given {@code predicate} using {@code value} as input.

* *

The function throws {@link PreconditionViolationException} if the * predicate is false.

* * @param value The value * @param condition The predicate * @param The type of values * * @return value * * @throws PreconditionViolationException If the predicate is false */ public static T checkPrecondition( final T value, final ContractConditionType condition) throws PreconditionViolationException { return checkPrecondition( value, condition.predicate(), condition.describer()); } /** *

Evaluate the given {@code predicate} using {@code value} as input.

* *

The function throws {@link PreconditionViolationException} if the * predicate is false.

* * @param value The value * @param predicate The predicate * @param describer A describer for the predicate * @param The type of values * * @return value * * @throws PreconditionViolationException If the predicate is false */ public static T checkPrecondition( final T value, final Predicate predicate, final Function describer) { final boolean ok; try { ok = predicate.test(value); } catch (final Throwable e) { final Violations violations = singleViolation(failedPredicate(e)); throw new PreconditionViolationException( failedMessage(value, violations), e, violations.count()); } return innerCheck(value, ok, describer); } /** *

Evaluate the given {@code predicate} using {@code value} as input.

* *

The function throws {@link PreconditionViolationException} if the * predicate is false.

* * @param value The value * @param condition The predicate * @param describer A describer for the predicate * @param The type of values * * @return value * * @throws PreconditionViolationException If the predicate is false */ public static T checkPrecondition( final T value, final boolean condition, final Function describer) { return innerCheck(value, condition, describer); } /** * A specialized version of {@link #checkPrecondition(Object, boolean, * Function)} that does not mention an input value. * * @param condition The predicate * @param message The predicate description * * @throws PreconditionViolationException Iff {@code predicate == false} */ public static void checkPrecondition( final boolean condition, final String message) throws PreconditionViolationException { if (!condition) { final Violations violations = singleViolation(message); throw new PreconditionViolationException( failedMessage("", violations), null, violations.count()); } } /** * A specialized version of {@link #checkPrecondition(Object, boolean, * Function)} that does not mention an input value. * * @param condition The predicate * @param message The predicate description supplier * * @throws PreconditionViolationException Iff {@code predicate == false} */ public static void checkPrecondition( final boolean condition, final Supplier message) throws PreconditionViolationException { if (!condition) { final Violations violations = singleViolation(applySupplierChecked(message)); throw new PreconditionViolationException( failedMessage("", violations), null, violations.count()); } } /** *

A version of {@link #checkPrecondition(boolean, String)} that constructs * a description message from the given format string and arguments.

* *

Note that the use of variadic arguments may entail allocating memory on * virtual machines that fail to eliminate the allocations with escape * analysis.

* * @param value The value * @param condition The predicate * @param format The format string * @param objects The format string arguments * @param The precise type of values * * @return {@code value} * * @since 1.1.0 */ public static T checkPreconditionV( final T value, final boolean condition, final String format, final Object... objects) { if (!condition) { final Violations violations = singleViolation(String.format(format, objects)); throw new PreconditionViolationException( failedMessage(value, violations), null, violations.count()); } return value; } /** *

A version of {@link #checkPrecondition(boolean, String)} that constructs * a description message from the given format string and arguments.

* *

Note that the use of variadic arguments may entail allocating memory on * virtual machines that fail to eliminate the allocations with escape * analysis.

* * @param condition The predicate * @param format The format string * @param objects The format string arguments * * @since 1.1.0 */ public static void checkPreconditionV( final boolean condition, final String format, final Object... objects) { checkPreconditionV("", condition, format, objects); } /** * An {@code int} specialized version of {@link #checkPrecondition(Object, * ContractConditionType)}. * * @param value The value * @param condition The predicate * * @return value * * @throws PreconditionViolationException If the predicate is false */ public static int checkPreconditionI( final int value, final ContractIntConditionType condition) throws PreconditionViolationException { return checkPreconditionI( value, condition.predicate(), condition.describer()); } /** * An {@code int} specialized version of {@link #checkPrecondition(Object, * ContractConditionType)}. * * @param value The value * @param predicate The predicate * @param describer The describer for the predicate * * @return value * * @throws PreconditionViolationException If the predicate is false */ public static int checkPreconditionI( final int value, final IntPredicate predicate, final IntFunction describer) { final boolean ok; try { ok = predicate.test(value); } catch (final Throwable e) { final Violations violations = singleViolation(failedPredicate(e)); throw new PreconditionViolationException( failedMessage(Integer.valueOf(value), violations), e, violations.count()); } return innerCheckI(value, ok, describer); } /** * An {@code int} specialized version of {@link #checkPrecondition(Object, * boolean, Function)}. * * @param value The value * @param condition The predicate * @param describer The describer for the predicate * * @return value * * @throws PreconditionViolationException If the predicate is false */ public static int checkPreconditionI( final int value, final boolean condition, final IntFunction describer) { return innerCheckI(value, condition, describer); } /** * A {@code long} specialized version of {@link #checkPrecondition(Object, * ContractConditionType)}. * * @param value The value * @param condition The predicate * * @return value * * @throws PreconditionViolationException If the predicate is false */ public static long checkPreconditionL( final long value, final ContractLongConditionType condition) throws PreconditionViolationException { return checkPreconditionL( value, condition.predicate(), condition.describer()); } /** * A {@code long} specialized version of {@link #checkPrecondition(Object, * Predicate, Function)} * * @param value The value * @param predicate The predicate * @param describer The describer of the predicate * * @return value * * @throws PreconditionViolationException If the predicate is false */ public static long checkPreconditionL( final long value, final LongPredicate predicate, final LongFunction describer) { final boolean ok; try { ok = predicate.test(value); } catch (final Throwable e) { final Violations violations = singleViolation(failedPredicate(e)); throw new PreconditionViolationException( failedMessage(Long.valueOf(value), violations), e, violations.count()); } return innerCheckL(value, ok, describer); } /** * A {@code long} specialized version of {@link #checkPrecondition(Object, * Predicate, Function)} * * @param condition The predicate * @param value The value * @param describer The describer of the predicate * * @return value * * @throws PreconditionViolationException If the predicate is false */ public static long checkPreconditionL( final long value, final boolean condition, final LongFunction describer) { return innerCheckL(value, condition, describer); } /** * A {@code double} specialized version of {@link #checkPrecondition(Object, * ContractConditionType)}. * * @param value The value * @param condition The predicate * * @return value * * @throws PreconditionViolationException If the predicate is false */ public static double checkPreconditionD( final double value, final ContractDoubleConditionType condition) throws PreconditionViolationException { return checkPreconditionD( value, condition.predicate(), condition.describer()); } /** * A {@code double} specialized version of {@link #checkPrecondition(Object, * Predicate, Function)} * * @param value The value * @param predicate The predicate * @param describer The describer of the predicate * * @return value * * @throws PreconditionViolationException If the predicate is false */ public static double checkPreconditionD( final double value, final DoublePredicate predicate, final DoubleFunction describer) { final boolean ok; try { ok = predicate.test(value); } catch (final Throwable e) { final Violations violations = singleViolation(failedPredicate(e)); throw new PreconditionViolationException( failedMessage(Double.valueOf(value), violations), e, violations.count()); } return innerCheckD(value, ok, describer); } /** * A {@code double} specialized version of {@link #checkPrecondition(Object, * boolean, Function)} * * @param value The value * @param condition The predicate * @param describer The describer of the predicate * * @return value * * @throws PreconditionViolationException If the predicate is false */ public static double checkPreconditionD( final double value, final boolean condition, final DoubleFunction describer) { return innerCheckD(value, condition, describer); } private static T innerCheck( final T value, final boolean condition, final Function describer) { if (!condition) { final Violations violations = singleViolation(applyDescriberChecked(value, describer)); throw new PreconditionViolationException( failedMessage(value, violations), null, violations.count()); } return value; } private static int innerCheckI( final int value, final boolean condition, final IntFunction describer) { if (!condition) { final Violations violations = singleViolation(applyDescriberIChecked(value, describer)); throw new PreconditionViolationException( failedMessage(Integer.valueOf(value), violations), null, violations.count()); } return value; } private static long innerCheckL( final long value, final boolean condition, final LongFunction describer) { if (!condition) { final Violations violations = singleViolation(applyDescriberLChecked(value, describer)); throw new PreconditionViolationException( failedMessage(Long.valueOf(value), violations), null, violations.count()); } return value; } private static double innerCheckD( final double value, final boolean condition, final DoubleFunction describer) { if (!condition) { final Violations violations = singleViolation(applyDescriberDChecked(value, describer)); throw new PreconditionViolationException( failedMessage(Double.valueOf(value), violations), null, violations.count()); } return value; } private static String failedMessage( final T value, final Violations violations) { final String line_separator = System.lineSeparator(); final StringBuilder sb = new StringBuilder(128); sb.append("Precondition violation."); sb.append(line_separator); sb.append(" Received: "); sb.append(value); sb.append(line_separator); sb.append(" Violated conditions: "); sb.append(line_separator); final String[] messages = violations.messages(); for (int index = 0; index < messages.length; ++index) { if (messages[index] != null) { sb.append(" ["); sb.append(index); sb.append("]: "); sb.append(messages[index]); sb.append(line_separator); } } return sb.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy