/*
 * @(#)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.
 * <p/>
 * DO NOT USE IT FOR OTHER PURPOSES!!!
 *
 * @author Alex Usun
 * @version 1.0
 */
public class Assert {

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

    /**
     * Asserts that the specified reference is not <code>null</code>.
     *
     * @param reference the reference to check
     *
     * @throws NullPointerException if the specified reference is <code>null</code>
     */
    public static void notNull(Object reference) {
        notNull(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 isTrue(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 truth
     */
    public static void isFalse(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 greater(long value, long bound, String message) {
        isTrue(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 greaterOrEqual(long value, long bound, String message) {
        isTrue(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 less(long value, long bound, String message) {
        isTrue(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 lessOrEqual(long value, long bound, String message) {
        isTrue(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 inRangeInclusive(long value,
                                        long lowerBound,
                                        long upperBound,
                                        String message) {
        greaterOrEqual(value, lowerBound, message);
        lessOrEqual(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 inRangeExclusive(long value,
                                        long lowerBound,
                                        long upperBound,
                                        String message) {
        greater(value, lowerBound, message);
        less(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 areEqual(long leftValue, long rightValue, String message) {
        isTrue(leftValue == rightValue, message);
    }

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

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

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

    /**
     * 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 isValidState(boolean condition, String message) {
        if (!condition) {
            throw new IllegalStateException(message);
        }
    }

    public static void isValidPort(int port) {
        inRangeInclusive(port, 1, 65535, "Bad port value.");
    }

    public static void isContained(Object value, Object[] array, String message) {
        for (int i = 0; i < array.length; ++i) {
            Object o = array[i];
            if (o == null && value == null) {
                return;
            }
            if (value != null && value.equals(o)) {
                return;
            }
        }

        throw new IllegalArgumentException(message);
    }

    /**
     * Private constructor to avoid unneccessary instantiation.
     */
    private Assert() {
        // empty
    }

}
