net.sf.qualitycheck.Check Maven / Gradle / Ivy
/*******************************************************************************
* Copyright 2013 André Rouél
* Copyright 2013 Dominik Seichter
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package net.sf.qualitycheck;
import java.lang.annotation.Annotation;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Map;
import java.util.regex.Pattern;
import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.sf.qualitycheck.exception.IllegalArgumentNotContainedException;
import net.sf.qualitycheck.exception.IllegalEmptyArgumentException;
import net.sf.qualitycheck.exception.IllegalInstanceOfArgumentException;
import net.sf.qualitycheck.exception.IllegalMissingAnnotationException;
import net.sf.qualitycheck.exception.IllegalNaNArgumentException;
import net.sf.qualitycheck.exception.IllegalNegativeArgumentException;
import net.sf.qualitycheck.exception.IllegalNotEqualException;
import net.sf.qualitycheck.exception.IllegalNotGreaterThanException;
import net.sf.qualitycheck.exception.IllegalNotLesserThanException;
import net.sf.qualitycheck.exception.IllegalNotNullArgumentException;
import net.sf.qualitycheck.exception.IllegalNullArgumentException;
import net.sf.qualitycheck.exception.IllegalNullElementsException;
import net.sf.qualitycheck.exception.IllegalNumberArgumentException;
import net.sf.qualitycheck.exception.IllegalNumericArgumentException;
import net.sf.qualitycheck.exception.IllegalPatternArgumentException;
import net.sf.qualitycheck.exception.IllegalPositionIndexException;
import net.sf.qualitycheck.exception.IllegalRangeException;
import net.sf.qualitycheck.exception.IllegalStateOfArgumentException;
import net.sf.qualitycheck.exception.RuntimeInstantiationException;
/**
* This class offers simple static methods to test your arguments to be valid.
*
* Checks should be added to all arguments of all public methods in your class to assure that only valid values can be
* encountered within your class. This is major step to avoid technical errors like NullPointerExceptions or
* IndexOutOfBoundsException in your code.
*
* @author André Rouél
* @author Dominik Seichter
*/
public final class Check {
/**
* Holder for the regular expression to determine numeric values. Using the holder pattern guarantees that the
* regular expression is initialized before the first use (thread safe!) and that it is only initialized if it is
* needed. So, we do not pay any performance bounty for regular expressions when using other checks.
*/
protected static final class NumericRegularExpressionHolder {
private static final Pattern NUMERIC_REGEX = Pattern.compile("[0-9]+");
@Nonnull
public static Pattern getPattern() {
return NUMERIC_REGEX;
}
}
/**
* Representation of an empty argument name.
*/
private static final String EMPTY_ARGUMENT_NAME = "";
/**
* Checks the passed {@code value} against the ranges of the given datatype.
*
* @param value
* value which must be a number and in the range of the given datatype.
* @param type
* requested return value type, must be a subclass of {@code Number}
* @return a number
*
* @throws NumberFormatException
* if the given value can not be parsed as a number
*/
private static Number checkNumberInRange(final String value, final Class type) {
final Number ret;
if (type.equals(Byte.class)) {
final Number number = new BigInteger(value);
NumberInRange.checkByte(number);
ret = Byte.valueOf(number.byteValue());
} else if (type.equals(Double.class)) {
final Number number = new BigDecimal(value);
NumberInRange.checkDouble(number);
ret = Double.valueOf(number.doubleValue());
} else if (type.equals(Float.class)) {
final Number number = new BigDecimal(value);
NumberInRange.checkFloat(number);
ret = Float.valueOf(number.floatValue());
} else if (type.equals(Integer.class)) {
final Number number = new BigInteger(value);
NumberInRange.checkInteger(number);
ret = Integer.valueOf(number.intValue());
} else if (type.equals(Long.class)) {
final Number number = new BigInteger(value);
NumberInRange.checkLong(number);
ret = Long.valueOf(number.longValue());
} else if (type.equals(Short.class)) {
final Number number = new BigInteger(value);
NumberInRange.checkShort(number);
ret = Short.valueOf(number.shortValue());
} else if (type.equals(BigInteger.class)) {
ret = new BigInteger(value);
} else if (type.equals(BigDecimal.class)) {
ret = new BigDecimal(value);
} else {
throw new IllegalNumberArgumentException("Return value is no known subclass of 'java.lang.Number': " + type.getName());
}
return ret;
}
/**
* Ensures that an element {@code needle} is contained in a collection {@code haystack}.
*
*
* This is in particular useful if you want to check whether an enum value is contained in an {@code EnumSet}. The
* check is implemented using {@link java.util.Collection#contains(Object)}.
*
*
* We recommend to use the overloaded method {@link Check#contains(Collection, Object, String)} and pass as second
* argument the name of the parameter to enhance the exception message.
*
* @param haystack
* A collection which must contain {@code needle}
* @param needle
* An object that must be contained into a collection.
* @return the passed argument {@code needle}
*
* @throws IllegalArgumentNotContainedException
* if the passed {@code needle} can not be found in {@code haystack}
*/
@ArgumentsChecked
@Throws({ IllegalNullArgumentException.class, IllegalArgumentNotContainedException.class })
public static T contains(@Nonnull final Collection haystack, @Nonnull final T needle) {
Check.notNull(haystack, "haystack");
Check.notNull(needle, "needle");
if (!haystack.contains(needle)) {
throw new IllegalArgumentNotContainedException();
}
return needle;
}
/**
* Ensures that an element {@code needle} is contained in a collection {@code haystack}.
*
*
* This is in particular useful if you want to check whether an enum value is contained in an {@code EnumSet}. The
* check is implemented using {@link java.util.Collection#contains(Object)}.
*
* @param haystack
* A collection which must contain {@code needle}
* @param needle
* An object that must be contained into a collection.
* @param name
* name of argument of {@code needle}
* @return the passed argument {@code needle}
*
* @throws IllegalArgumentNotContainedException
* if the passed {@code needle} can not be found in {@code haystack}
*/
@ArgumentsChecked
@Throws({ IllegalNullArgumentException.class, IllegalArgumentNotContainedException.class })
public static T contains(@Nonnull final Collection haystack, @Nonnull final T needle, @Nonnull final String name) {
Check.notNull(haystack, "haystack");
Check.notNull(needle, "needle");
if (!haystack.contains(needle)) {
throw new IllegalArgumentNotContainedException(name);
}
return needle;
}
/**
* Checks if the given array contains {@code null}.
*
* @param array
* reference to an array
* @return {@code true} if the array contains {@code null}, otherwise {@code false}
*/
private static boolean containsNullElements(@Nonnull final Object[] array) {
boolean containsNull = false;
for (final Object o : array) {
if (o == null) {
containsNull = true;
break;
}
}
return containsNull;
}
/**
* Ensures that a passed boolean is equal to another boolean. The comparison is made using
* expected != check.
*
*
* We recommend to use the overloaded method {@link Check#equals(boolean, boolean, String)} and pass as second
* argument the name of the parameter to enhance the exception message.
*
* @param expected
* Expected value
* @param check
* boolean to be checked
* @return the passed boolean argument {@code check}
*
* @throws IllegalNotEqualException
* if both argument values are not equal
*/
@Throws(IllegalNotEqualException.class)
public static boolean equals(@Nonnull final boolean expected, @Nonnull final boolean check) { // NOSONAR
// Sonar warns about suspicious equals method name, as the name is intended deactivate sonar
if (expected != check) {
throw new IllegalNotEqualException();
}
return check;
}
/**
* Ensures that a passed boolean is equal to another boolean. The comparison is made using
* expected != check.
*
* @param expected
* Expected value
* @param check
* boolean to be checked
* @param message
* an error message describing why the booleans must equal (will be passed to
* {@code IllegalNotEqualException})
* @return the passed boolean argument {@code check}
*
* @throws IllegalNotEqualException
* if both argument values are not equal
*/
@Throws(IllegalNotEqualException.class)
public static boolean equals(@Nonnull final boolean expected, @Nonnull final boolean check, final String message) { // NOSONAR
// Sonar warns about suspicious equals method name, as the name is intended deactivate sonar
if (expected != check) {
throw new IllegalNotEqualException(message);
}
return check;
}
/**
* Ensures that a passed byte is equal to another byte. The comparison is made using expected != check.
*
*
* We recommend to use the overloaded method {@link Check#equals(byte, byte, String)} and pass as second argument
* the name of the parameter to enhance the exception message.
*
* @param expected
* Expected value
* @param check
* byte to be checked
* @return the passed byte argument {@code check}
*
* @throws IllegalNotEqualException
* if both argument values are not equal
*/
@Throws(IllegalNotEqualException.class)
public static byte equals(@Nonnull final byte expected, @Nonnull final byte check) { // NOSONAR
// Sonar warns about suspicious equals method name, as the name is intended deactivate sonar
if (expected != check) {
throw new IllegalNotEqualException();
}
return check;
}
/**
* Ensures that a passed byte is equal to another byte. The comparison is made using expected != check.
*
* @param expected
* Expected value
* @param check
* byte to be checked
* @param message
* an error message describing why the bytes must equal (will be passed to
* {@code IllegalNotEqualException})
* @return the byte boolean argument {@code check}
*
* @throws IllegalNotEqualException
* if both argument values are not equal
*/
@Throws(IllegalNotEqualException.class)
public static byte equals(@Nonnull final byte expected, @Nonnull final byte check, final String message) { // NOSONAR
// Sonar warns about suspicious equals method name, as the name is intended deactivate sonar
if (expected != check) {
throw new IllegalNotEqualException(message);
}
return check;
}
/**
* Ensures that a passed char is equal to another char. The comparison is made using expected != check.
*
*
* We recommend to use the overloaded method {@link Check#equals(char, char, String)} and pass as second argument
* the name of the parameter to enhance the exception message.
*
* @param expected
* Expected value
* @param check
* char to be checked
* @return the passed char argument {@code check}
*
* @throws IllegalNotEqualException
* if both argument values are not equal
*/
@Throws(IllegalNotEqualException.class)
public static char equals(@Nonnull final char expected, @Nonnull final char check) { // NOSONAR
// Sonar warns about suspicious equals method name, as the name is intended deactivate sonar
if (expected != check) {
throw new IllegalNotEqualException();
}
return check;
}
/**
* Ensures that a passed char is equal to another char. The comparison is made using expected != check.
*
* @param expected
* Expected value
* @param check
* char to be checked
* @param message
* an error message describing why the chars must equal (will be passed to
* {@code IllegalNotEqualException})
* @return the passed char argument {@code check}
*
* @throws IllegalNotEqualException
* if both argument values are not equal
*/
@Throws(IllegalNotEqualException.class)
public static char equals(@Nonnull final char expected, @Nonnull final char check, final String message) { // NOSONAR
// Sonar warns about suspicious equals method name, as the name is intended deactivate sonar
if (expected != check) {
throw new IllegalNotEqualException(message);
}
return check;
}
/**
* Ensures that a passed intH is equal to another int. The comparison is made using expected != check.
*
*
* We recommend to use the overloaded method {@link Check#equals(int, int, String)} and pass as second argument the
* name of the parameter to enhance the exception message.
*
* @param expected
* Expected value
* @param check
* int to be checked
* @return the passed int argument {@code check}
*
* @throws IllegalNotEqualException
* if both argument values are not equal
*/
@Throws(IllegalNotEqualException.class)
public static int equals(@Nonnull final int expected, @Nonnull final int check) { // NOSONAR
// Sonar warns about suspicious equals method name, as the name is intended deactivate sonar
if (expected != check) {
throw new IllegalNotEqualException();
}
return check;
}
/**
* Ensures that a passed int is equal to another int. The comparison is made using expected != check.
*
* @param expected
* Expected value
* @param check
* int to be checked
* @param message
* an error message describing why the ints must equal (will be passed to
* {@code IllegalNotEqualException})
* @return the passed int argument {@code check}
*
* @throws IllegalNotEqualException
* if both argument values are not equal
*/
@Throws(IllegalNotEqualException.class)
public static int equals(@Nonnull final int expected, @Nonnull final int check, final String message) { // NOSONAR
// Sonar warns about suspicious equals method name, as the name is intended deactivate sonar
if (expected != check) {
throw new IllegalNotEqualException(message);
}
return check;
}
/**
* Ensures that a passed long is equal to another long. The comparison is made using expected != check.
*
*
* We recommend to use the overloaded method {@link Check#equals(long, long, String)} and pass as second argument
* the name of the parameter to enhance the exception message.
*
* @param expected
* Expected value
* @param check
* long to be checked
* @return the passed long argument {@code check}
*
* @throws IllegalNotEqualException
* if both argument values are not equal
*/
@Throws(IllegalNotEqualException.class)
public static long equals(@Nonnull final long expected, @Nonnull final long check) { // NOSONAR
// Sonar warns about suspicious equals method name, as the name is intended deactivate sonar
if (expected != check) {
throw new IllegalNotEqualException();
}
return check;
}
/**
* Ensures that a passed long is equal to another long. The comparison is made using expected != check.
*
* @param expected
* Expected value
* @param check
* long to be checked
* @param message
* an error message describing why the longs must equal (will be passed to
* {@code IllegalNotEqualException})
* @return the passed long argument {@code check}
*
* @throws IllegalNotEqualException
* if both argument values are not equal
*/
@Throws(IllegalNotEqualException.class)
public static long equals(@Nonnull final long expected, @Nonnull final long check, final String message) { // NOSONAR
// Sonar warns about suspicious equals method name, as the name is intended deactivate sonar
if (expected != check) {
throw new IllegalNotEqualException(message);
}
return check;
}
/**
* Ensures that a passed short is equal to another short. The comparison is made using
* expected != check.
*
*
* We recommend to use the overloaded method {@link Check#equals(short, short, String)} and pass as second argument
* the name of the parameter to enhance the exception message.
*
* @param expected
* Expected value
* @param check
* short to be checked
* @return the passed short argument {@code check}
*
* @throws IllegalNotEqualException
* if both argument values are not equal
*/
@Throws(IllegalNotEqualException.class)
public static short equals(@Nonnull final short expected, @Nonnull final short check) { // NOSONAR
// Sonar warns about suspicious equals method name, as the name is intended deactivate sonar
if (expected != check) {
throw new IllegalNotEqualException();
}
return check;
}
/**
* Ensures that a passed short is equal to another short. The comparison is made using
* expected != check.
*
* @param expected
* Expected value
* @param check
* short to be checked
* @param message
* an error message describing why the shorts must equal (will be passed to
* {@code IllegalNotEqualException})
* @return the passed short {@code check}
*
* @throws IllegalNotEqualException
* if both argument values are not equal
*/
@Throws(IllegalNotEqualException.class)
public static short equals(@Nonnull final short expected, @Nonnull final short check, final String message) { // NOSONAR
// Sonar warns about suspicious equals method name, as the name is intended deactivate sonar
if (expected != check) {
throw new IllegalNotEqualException(message);
}
return check;
}
/**
* Ensures that a passed {@code Comparable} is equal to another {@code Comparable}. The comparison is made using
* {@code expected.compareTo(check) != 0}.
*
*