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

io.github.bhowell2.apilib.checks.Check Maven / Gradle / Ivy

The newest version!
package io.github.bhowell2.apilib.checks;

import io.github.bhowell2.apilib.ApiLibSettings;
import io.github.bhowell2.apilib.ApiSingleParam;

import java.util.Map;

/**
 * Intended to be used to check the value of a single parameter - a parameter that does not contain
 * named sub-parameters (e.g., Map/JsonObject). This is because the Check does not return the names
 * of any parameters, only whether or not the check was successful and (optionally) a message
 * indicating the reason for failure.
 *
 * Failure messages should.
 * @author Blake Howell
 */
@FunctionalInterface
public interface Check {

	/**
	 * Provides the functionality to always pass a check, regardless fo the parameter's
	 * type. This should be used in rare cases and will basically only ensure that the
	 * user provided the paramter.
	 * @param  typing
	 * @return a check that always passes
	 */
	static  Check alwaysPassUnsafeTyping() {
		return param -> Check.Result.success();
	}

	/**
	 * Should be used when it is only necessary to check if the parameter is provided
	 * and is of the correct type. The actual value does not matter. This can be used
	 * with {@link ApiSingleParam#canBeNull} as true or false. If {@code canBeNull=true}
	 * then this will pass either way. If {@code canBeNull=false} then this will cause
	 * {@link ApiSingleParam#check(Map)}} to only pass if the parameter is NOT null and
	 * is of the correct type.
	 *
	 * @param clazz class (or parent class) the parameter must be an instance of (will fail if it is not)
	 * @param  type of the parameter
	 */
	static  Check alwaysPass(Class clazz) {
		return alwaysPass(clazz, ApiLibSettings.DEFAULT_CASTING_ERROR_MESSAGE);
	}

	/**
	 * Should be used when it is only necessary to check if the parameter is provided
	 * and is of the correct type. The actual value does not matter. This can be used
	 * with {@link ApiSingleParam#canBeNull} as true or false. If {@code canBeNull=true}
	 * then this will pass either way. If {@code canBeNull=false} then this will cause
	 * {@link ApiSingleParam#check(Map)}} to only pass if the parameter is NOT null and
	 * is of the correct type.
	 *
	 * @param clazz class (or parent class) the parameter must be an instance of (will fail if it is not)
	 * @param invalidClassErrorMessage failure message returned if param is not of correct type
	 * @param  type of the parameter
	 * @return
	 */
	static  Check alwaysPass(Class clazz, String invalidClassErrorMessage) {
		return param -> clazz.isInstance(param)
			?
			Check.Result.success()
			:
			Check.Result.failure(invalidClassErrorMessage);

	}

	/**
	 * Should be used when the parameter check should always fail regardless of the value and
	 * parameter class type - this does not type check like {@link #alwaysPass(Class)}, since
	 * it always fails.
	 *
	 * @param  type of the parameter
	 * @return a check that always fails
	 */
	@SuppressWarnings("unchecked")
	static  Check alwaysFail() {
		return Result.ALWAYS_FAIL_UNTYPED_CHECK;
	}

	/**
	 * Should be used when the parameter check should always fail regardless of the value and
	 * parameter class type - this does not type check like {@link #alwaysPass(Class)}, since
	 * it always fails.
	 *
	 * @param failureMessage the message to return with the check failure
	 * @param  type of the parameter (is not actually checked)
	 * @return a check that always fails
	 */
	static  Check alwaysFail(String failureMessage) {
		return (T t) -> Result.failure(failureMessage);
	}

	/**
	 * Check that the value of the parameter satisfies this check.
	 * @param param the parameter value to check
	 * @return
	 */
	Result check(T param);

	/**
	 * Allows for returning whether or not the parameter's value was successfully
	 * checked or that it failed and an failure message can optionally be returned.
	 */
	final class Result {

		public String failureMessage;

		/**
		 * Requiring use of static creation methods to disambiguate a successful result
		 * (no param in constructor) and a failure (requiring value for failure message).
		 */
		private Result() {}

		// for failure
		private Result(String failureMessage) {
			/*
			 * this cannot be null due to successful and failed methods below
			 * would need to add additional boolean for success status otherwise
			 * */
			this.failureMessage = failureMessage;
		}

		/**
		 * Whether or not the check was successful.
		 */
		public boolean successful() {
			return this.failureMessage == null;
		}

		/**
		 * Whether or not the check failed.
		 */
		public boolean failed() {
			return this.failureMessage != null;
		}

		/* Static Creation Methods */

		/**
		 * Avoid creating a new object every time a check is successful.
		 */
		private static Result SUCCESSFUL = new Result();

		/* Implementation  */
		public static Result success() {
			return SUCCESSFUL;
		}

		/**
		 * Creates a failed check result with the default failure message:
		 * {@link ApiLibSettings#DEFAULT_INVALID_PARAMETER_MESSAGE}.
		 */
		public static Result failure() {
			return new Result(ApiLibSettings.DEFAULT_INVALID_PARAMETER_MESSAGE);
		}

		/**
		 * Creates a failed check result with the provided failure message.
		 * If the failure message is null it will be set to
		 * {@link ApiLibSettings#DEFAULT_INVALID_PARAMETER_MESSAGE}.
		 */
		public static Result failure(String failureMessage) {
			if (failureMessage == null) {
				/*
				 * Cannot be null or would need to add a boolean to differentiate a failure
				 * from success, due to how successful and failure methods are implemented.
				 * */
				return new Result(ApiLibSettings.DEFAULT_INVALID_PARAMETER_MESSAGE);
			}
			return new Result(failureMessage);
		}

		/**
		 * To avoid creating a new always failing check every time with {@link Check#alwaysFail()},
		 * this is used instead. It is created here in a package-private manner so that it is not
		 * accessible to the public, but can be used by the outer interface.
		 */
		static final Check ALWAYS_FAIL_UNTYPED_CHECK = t -> Result.failure();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy