/*
 * @(#)Assert.java
 *
 * Copyright (c) 2002-2003 JSCAPE
 * 1147 S. 53rd Pl., Mesa, Arizona, 85206, U.S.A.
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of
 * JSCAPE. ("Confidential Information").  You shall not disclose such
 * Confidential Information and shall use it only in accordance with
 * the terms of the license agreement you entered into with JSCAPE.
 */

/*
 * Classname: Assert
 *
 * Version: 1.0
 *
 * Author: Alex Usun
 */
package com.jscape.util;

/**
 * The utility class for various run-time verifications.
 * It is intended to use as standard "assert" keyword
 * for method parameter verification.
 *
 * @author Alex Usun
 */
public final class Parameters {

    /**
     * Asserts that the specified reference is not <code>null</code>.
     *
     * @param reference the reference to check
     * @param message   the error message
     *
     * @throws IllegalArgumentException if the specified reference is <code>null</code>
     */
    public static void assertNotNull(Object reference, String message) {
        if (reference == null) {
            throw new IllegalArgumentException(message);
        }
    }

    /**
     * Asserts that the specified reference is not <code>null</code>.
     *
     * @param reference the reference to check
     *
     * @throws IllegalArgumentException if the specified reference is <code>null</code>
     */
    public static void assertNotNull(Object reference) {
        assertNotNull(reference, "Null reference is not allowed.");
    }

    /**
     * Asserts that the specified condition is truth.
     *
     * @param condition the condition to check
     * @param message   the error message
     *
     * @throws IllegalArgumentException if the specified condition is false
     */
    public static void assertTrue(boolean condition, String message) {
        if (!condition) {
            throw new IllegalArgumentException(message);
        }
    }

    /**
     * Asserts that the specified condition is false.
     *
     * @param condition the condition to check
     * @param message   the error message
     *
     * @throws IllegalArgumentException if the specified condition is true
     */
    public static void assertFalse(boolean condition, String message) {
        if (condition) {
            throw new IllegalArgumentException(message);
        }
    }

    /**
     * Asserts that the specified value is greater than the lower bound.
     *
     * @param value   the value to check
     * @param bound   the value lower bound
     * @param message the error message
     *
     * @throws IllegalArgumentException if the specified value is not greater than the lower bound
     */
    public static void assertGreater(long value, long bound, String message) {
        assertTrue(value > bound, message);
    }

    /**
     * Asserts that the specified value is greater or equal than the lower bound.
     *
     * @param value   the value to check
     * @param bound   the value lower bound
     * @param message the error message
     *
     * @throws IllegalArgumentException if the specified value is less than the lower bound
     */
    public static void assertGreaterOrEqual(long value, long bound, String message) {
        assertTrue(value >= bound, message);
    }

    /**
     * Asserts that the specified value is less that the upper bound.
     *
     * @param value   the value to check
     * @param bound   the value upper bound
     * @param message the error message
     *
     * @throws IllegalArgumentException if the specified value is not less than the upper bound
     */
    public static void assertLesser(long value, long bound, String message) {
        assertTrue(value < bound, message);
    }

    /**
     * Asserts that the specified value is less or equal that the upper bound.
     *
     * @param value   the value to check
     * @param bound   the value upper bound
     * @param message the error message
     *
     * @throws IllegalArgumentException if the specified value is not greater than the upper bound
     */
    public static void assertLesserOrEqual(long value, long bound, String message) {
        assertTrue(value <= bound, message);
    }

    /**
     * Asserts that the specified value is in range inclusive.
     *
     * @param value      the value to check
     * @param lowerBound the value lower bound
     * @param upperBound the value upper bound
     * @param message    the error message
     *
     * @throws IllegalArgumentException if the specified value is not in range inclusive
     */
    public static void assertInRangeInclusive(long value,
                                              long lowerBound,
                                              long upperBound,
                                              String message) {
        assertGreaterOrEqual(value, lowerBound, message);
        assertLesserOrEqual(value, upperBound, message);
    }

    /**
     * Asserts that the specified value is in range exclusive.
     *
     * @param value      the value to check
     * @param lowerBound the value lower bound
     * @param upperBound the value upper bound
     * @param message    the error message
     *
     * @throws IllegalArgumentException if the specified value is not in range exclusive
     */
    public static void assertInRangeExclusive(long value,
                                              long lowerBound,
                                              long upperBound,
                                              String message) {
        assertGreater(value, lowerBound, message);
        assertLesser(value, upperBound, message);
    }

    /**
     * Asserts that two specified values are equal.
     *
     * @param leftValue  the first value
     * @param rightValue the second value
     * @param message    the error message
     *
     * @throws IllegalArgumentException if the specified values are not equal
     */
    public static void assertEquals(long leftValue, long rightValue, String message) {
        assertTrue(leftValue == rightValue, message);
    }

    /**
     * Asserts that two specified objects are equal.
     *
     * @param leftObject  the first object
     * @param rightObject the second object
     * @param message     the error message
     *
     * @throws IllegalArgumentException if some of the objects are <code>null</code> or the specified objects are not equal
     */
    public static void assertEquals(Object leftObject, Object rightObject, String message) {
        assertNotNull(leftObject);
        assertNotNull(rightObject);
        assertTrue(leftObject.equals(rightObject), message);
    }

    /**
     * Asserts that the specified array parameters are valid.
     *
     * @param array  the array to check
     * @param offset the array offset
     * @param length the data length
     *
     * @throws IllegalArgumentException if the array reference is <code>null</code> of the offset or length parameters are invalid
     */
    public static void assertArrayValid(byte[] array, int offset, int length) {
        assertInRangeInclusive(offset, 0, array.length, "Bad array offset.");
        assertGreaterOrEqual(length, 0, "Bad array length.");
        assertLesserOrEqual(offset + length, array.length, "Bad array offset or length.");
    }

    /**
     * Asserts that the specified string are valid.
     *
     * @param string, string to check
     *
     * @throws IllegalArgumentException if the string reference is <code>null</code> or the string is empty
     */
    public static void assertStringValid(String string) {
        assertNotNull(string);
        assertGreater(string.length(), 0, "Bad string length.");
    }

    /**
     * Checks if state condition is true.
     *
     * @param condition state condition to check
     * @param message   error message
     *
     * @throws IllegalStateException if state condition is false
     */
    public static void assertStateValid(boolean condition, String message) {
        if (!condition) {
            throw new IllegalStateException(message);
        }
    }

    /**
     * Private constructor to avoid unnecessary instantiation.
     */
    private Parameters() {
        // empty
    }

}
