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

io.github.bhowell2.apilib.ApiParamBase Maven / Gradle / Ivy

package io.github.bhowell2.apilib;


import io.github.bhowell2.apilib.errors.ApiParamError;

import java.util.List;

/**
 * Base that all parameters in ApiLib extend, provides common functionality.
 * @author Blake Howell
 */
public abstract class ApiParamBase implements ApiParam {

	public final String keyName, displayName, invalidErrorMessage;
	public final boolean canBeNull;

	/**
	 * Common builder for all implemented parameter types.
	 * @param  the extending builder. needed to provide common fluent functionality
	 */
	public static abstract class Builder<
		P extends ApiParamBase,
		B extends Builder
		> {

		String keyName, displayName, invalidErrorMessage;
		boolean canBeNull = false;

		public Builder(String keyName) {
			this.keyName = keyName;
		}

		/**
		 * Used by extending classes to check varargs.
		 */
		@SafeVarargs
		protected static  void checkVarArgsNotNullAndValuesNotNull(T... args) {
			if (args == null) {
				throw new IllegalArgumentException("Cannot add null parameters.");
			}
			for (T a : args) {
				if (a == null) {
					throw new IllegalArgumentException("Cannot add null in var args array.");
				}
			}
		}

		/**
		 * Sets the name of the parameter that will be returned in {@link ApiParamError}
		 * if an error occurs with the parameter. This allows for easily retrieving a
		 * name that can be displayed to the user with an informative error message.
		 *
		 * @param displayName display name to use. default is null
		 * @return this builder
		 */
		@SuppressWarnings("unchecked")
		public B setDisplayName(String displayName) {
			this.displayName = displayName;
			return (B) this;
		}

		/**
		 * Set whether or not the value of the parameter can be SET to null.
		 * Note there is a difference between a parameter being set to null
		 * and just not being provided. In the case of {@link java.util.Map}
		 * {@link java.util.Map#get(Object)} returns null if nothing has been
		 * set for the given key OR if the value for the key has been SET to
		 * null; to determine whether this was SET to null or just does not
		 * exists {@link java.util.Map#containsKey(Object)} is used.
		 *
		 * @return this builder
		 */
		@SuppressWarnings("unchecked")
		public B setCanBeNull(boolean canBeNull) {
			this.canBeNull = canBeNull;
			return (B) this;
		}

		/**
		 * Sets an error message to be returned that overrides the failure message
		 * from {@link io.github.bhowell2.apilib.checks.Check.Result} or even the
		 * error message of {@link ApiParamError} in the case of a container
		 * parameter such as {@link ApiMapParam} or {@link ApiCollectionParam}.
		 * This can be useful when the user wants to return all of the requirements
		 * for a parameter in a single string, rather than only what caused the
		 * failure with the current request.
		 *
		 * @return this builder
		 */
		@SuppressWarnings("unchecked")
		public B setInvalidErrorMessage(String errorMessage) {
			this.invalidErrorMessage = errorMessage;
			return (B) this;
		}

		/**
		 * Build the parameter of type {@code P}.
		 */
		public abstract P build();

	}

	protected static  boolean arrayIsNotNullOrEmpty(T[] array) {
		return array != null && array.length > 0;
	}

	/**
	 * Used by various extending classes to test whether or not a list is
	 * empty and/or empty to avoid accessing null or empty lists.
	 * @return true of the list is not null and not empty
	 */
	protected static boolean listIsNotNullOrEmpty(List list) {
		return list != null && list.size() > 0;
	}

	@SuppressWarnings("unchecked")
	protected static  T[] getArrayIfNotNullOrEmpty(List list, T[] emptyCollection) {
		return listIsNotNullOrEmpty(list)
			? list.toArray(emptyCollection)
			: null;
	}

	protected ApiParamBase(Builder builder) {
		this.keyName = builder.keyName;
		this.displayName = builder.displayName;
		this.invalidErrorMessage = builder.invalidErrorMessage;
		this.canBeNull = builder.canBeNull;
	}

	/**
	 * The result returned from {@link ApiParam#check(Object)}. This is just common
	 * functionality shared by all param results. Basically a keyName should be returned
	 * (except, perhaps, for the result of {@link ApiCustomParam}) or an
	 * {@link ApiParamError} should be returned which, of course, indicates an error
	 * occurred.
	 */
	public static abstract class Result {

		public final String keyName;
		public final ApiParamError error;

		protected Result(String keyName) {
			this.keyName = keyName;
			this.error = null;
		}

		protected Result(ApiParamError error) {
			// must enforce this for successful and failed methods below to return correctly
			if (error == null) {
				throw new IllegalArgumentException("Cannot create failed check result with null.");
			}
			this.error = error;
			// keyName should be obtained in the ApiParamError
			this.keyName = null;
		}

		public boolean failed() {
			return error != null;
		}

		public boolean successful() {
			return error == null;
		}

		/**
		 * Will have an error tuple if the parameter check fails, otherwise it is null.
		 *
		 * @return ErrorTuple containing the parameter name, error message, and error type.
		 */
		public ApiParamError getError() {
			return error;
		}

		/**
		 * @return whether or not the key name has been set (is not null) for this check result
		 */
		public boolean hasKeyName() {
			return this.keyName != null;
		}

		/**
		 * Returns the key name for this check result. Not all parameters
		 * results will have a key name (e.g., root level ApiMapParams or
		 * inner ApiCollectionParams).
		 * Can use {@link #hasKeyName()} to ensure this will not be null
		 * if desired.
		 *
		 * @return name of successfully checked parameter - may be null
		 */
		public String getKeyName() {
			return keyName;
		}

	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy