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

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

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

import io.github.bhowell2.apilib.checks.CollectionIndexCheck;
import io.github.bhowell2.apilib.checks.Check;
import io.github.bhowell2.apilib.errors.ApiErrorType;
import io.github.bhowell2.apilib.errors.ApiParamError;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * This is a base class for ApiCollectionParam implementations such as
 * {@link ApiListParam} and {@link ApiArrayParam}.
 *
 * @param  the type of parameter from which the collection will be retrieved
 * @param  the parameter type of each index
 * @param  the collection type (e.g., for an array of Param type String, Collection type = String[])
 * @author Blake Howell
 */
public abstract class ApiCollectionParam
	extends ApiParamBase
{


	/**
	 * Checks used on the entire collection. This is most useful when needing
	 * to check the entire collection for some condition (e.g., unique numbers,
	 * or size). If only this was to be used, without the other index checks, then
	 * a simple {@link ApiSingleParam} could be used for the entire collection, but
	 * it's not, so here we are.
	 */
	final Check[] collectionChecks;

	/**
	 * Checks used on ALL indices of the array parameter. This, or
	 * {@link #individualIndexChecks} or {@link #indexMapCheck} or
	 * {@link #individualIndexMapChecks} is required for the innermost
	 * collection parameter (i.e., the ApiCollectionParam that does not
	 * have {@link #innerCollectionParam} set).
	 */
	final CollectionIndexCheck[] indexChecks;

	/**
	 * This is an array of arrays. The first array corresponds to the index to be
	 * checked and the inner array are the checks that should be run on the given
	 * index.
	 */
	final CollectionIndexCheck[][] individualIndexChecks;

	/**
	 * Map check that applies to all indices. Only this or {@link #individualIndexMapChecks}
	 * can be set, but not both - because their return values would override each other.
	 */
	final ApiMapParam indexMapCheck;

	/**
	 * Used to check each index with the individual ApiMapParam.
	 */
	final ApiMapParam[] individualIndexMapChecks;

	/**
	 * If the parameter is a multidimensional array this should be set to handle the
	 * inner array. This can be of arbitrary depth. The innermost array will have this
	 * set to null and is required to have at least some type of {@link CollectionIndexCheck}.
	 */
	final ApiCollectionParam innerCollectionParam;

	/**
	 * ArrayOrListParam builder base.
	 */
	protected static abstract class Builder<
		In,
		Param,
		Collection,
		B extends Builder,
		C extends ApiCollectionParam
		>
		extends ApiParamBase.Builder<
		ApiCollectionParam,
		B
		> {

		/*
		 * Currently this is not handled/used, but it may need to be in the future.
		 * This is ALMOST handled via a list.size check, but that would return
		 * ApiErrorType.INVALID_PARAMETER, rather than possibly a desired
		 * ApiErrorType.MISSING_PARAMETER for an empty array. For now it seems
		 * fine to allow the user to only return INVALID_PARAMETER rather than
		 * MISSING_PARAMETER on an empty collection as it is technically provided
		 * and invalid...
		 * */
		boolean returnMissingOnEmptyCollection;

		List> collectionChecks;
		List> indexChecks;
		List>> individualIndexChecks;
		ApiMapParam indexMapCheck;
		List individualIndexMapCheck;
		ApiCollectionParam innerCollectionParam;

		public Builder(String keyName) {
			super(keyName);
		}

		public Builder(String keyName, ApiCollectionParam copyFrom) {
			super(keyName);
			this.collectionChecks = arrayIsNotNullOrEmpty(copyFrom.collectionChecks)
				? new ArrayList<>(Arrays.asList(copyFrom.collectionChecks))
				: null;
			this.indexChecks = arrayIsNotNullOrEmpty(copyFrom.indexChecks)
				? new ArrayList<>(Arrays.asList(copyFrom.indexChecks))
				: null;
			this.individualIndexChecks = arrayIsNotNullOrEmpty(copyFrom.individualIndexChecks)
				? Arrays.stream(copyFrom.individualIndexChecks)
				        .map(Arrays::asList)
				        .collect(ArrayList::new,
				                 ArrayList::add,
				                 List::addAll)
				: null;
			this.indexMapCheck = copyFrom.indexMapCheck;
			this.individualIndexMapCheck = arrayIsNotNullOrEmpty(copyFrom.individualIndexMapChecks)
				? Arrays.asList(copyFrom.individualIndexMapChecks)
				: null;
		}

//		/**
//		 * Set whether or not the {@link ApiCollectionParam.Result} should return
//		 * {@link ApiErrorType#MISSING_PARAMETER} if the collection is empty.
//		 *
//		 * This is useful when {@link ApiMapParam#continueOnOptionalFailure} is set to
//		 * false, but the user does not want an emtpy (optional)collection to be added to
//		 * the list of {@link ApiMapParam.Result#checkedKeyNames}. In the case that the
//		 * parameter is required, this would be like setting {@link #setLengthCheck(Check)}
//		 * to {@code IntegerChecks.valueGreaterThan(0)}.
//		 *
//		 * @param returnMissingOnEmptyCollection
//		 * @return
//		 */
//		@SuppressWarnings("unchecked")
//		public B setReturnMissingOnEmptyCollection(boolean returnMissingOnEmptyCollection) {
//			this.returnMissingOnEmptyCollection = returnMissingOnEmptyCollection;
//			return (B) this;
//		}

		/**
		 * Sets a check for the length of the collection.
		 * (Alias of {@link #addCollectionChecks}.)
		 * @param sizeCheck check for size of index. can be greater, less, or equal to check
		 * @return this builder
		 */
		@SuppressWarnings("unchecked")
		public B setSizeCheck(Check sizeCheck) {
			return this.addCollectionChecks(collection -> {
				if (collection instanceof List) {
					return sizeCheck.check(((List) collection).size());
				}
				return sizeCheck.check(((Object[]) collection).length);
			});
		}

		/**
		 * Adds checks that are applied to the entire collection. E.g., a check
		 * that ensures the collection's size meets some criteria or that the
		 * collection has unique elements.
		 * @param checks to be applied to the entire collection
		 * @return this builder
		 */
		@SafeVarargs
		@SuppressWarnings("unchecked")
		public final B addCollectionChecks(Check... checks) {
			checkVarArgsNotNullAndValuesNotNull(checks);
			if (this.collectionChecks == null) {
				this.collectionChecks = new ArrayList<>(checks.length);
			}
			this.collectionChecks.addAll(Arrays.asList(checks));
			return (B) this;
		}

		/**
		 * Adds checks that are applied to each index of the collection. This takes
		 * normal {@link Check}s and wraps them with {@link CollectionIndexCheck}s. This
		 * allows for using regular checks when the actual index value is not needed
		 * for the check.
		 * @param indexChecks checks to be applied to each index
		 * @return this builder
		 */
		@SafeVarargs
		@SuppressWarnings("unchecked")
		public final B addIndexChecks(Check... indexChecks) {
			checkVarArgsNotNullAndValuesNotNull(indexChecks);
			return (B) this.addIndexChecks(Arrays.stream(indexChecks)
			                                     .map(CollectionIndexCheck::wrapCheck)
			                                     .>toArray(CollectionIndexCheck[]::new));
		}

		/**
		 * Adds checks that are applied to each index of the collection.
		 * @param indexChecks checks to be applied to each index
		 * @return this builder
		 */
		@SafeVarargs
		@SuppressWarnings("unchecked")
		public final B addIndexChecks(CollectionIndexCheck... indexChecks) {
			checkVarArgsNotNullAndValuesNotNull(indexChecks);
			if (this.indexChecks == null) {
				this.indexChecks = new ArrayList<>(indexChecks.length);
			}
			this.indexChecks.addAll(Arrays.asList(indexChecks));
			return (B) this;
		}

		/**
		 * Sets the list of checks that are to be applied to each index of the
		 * collection. Each index of the outer/container list contains an inner
		 * list of checks to be applied to that index of the collection.
		 *
		 * If these are set the collection parameter must be of the same length.
		 * If this is not desired the user could achieve the same effect with
		 * their own {@link CollectionIndexCheck}.
		 *
		 * @param individualIndexChecks list of list of checks (where the inner list's checks are
		 *                              applied to each index of the collection parameter)
		 * @return this builder
		 */
		@SuppressWarnings("unchecked")
		public B setIndividualIndexChecksWrapCheck(List>> individualIndexChecks) {
			this.individualIndexChecks =
				individualIndexChecks
					.stream()
					.map(checks -> checks.stream()
					                     .map(CollectionIndexCheck::wrapCheck)
					                     .collect(Collectors.toList()))
					.collect(Collectors.toList());
			return (B) this;
		}

		/**
		 * Sets the list of checks that are to be applied to each index of the
		 * collection. Each index of the outer/container list contains an inner
		 * list of checks to be applied to that index of the collection.
		 *
		 * If these are set the collection parameter must be of the same length.
		 * If this is not desired the user could achieve the same effect with
		 * their own {@link CollectionIndexCheck}.
		 *
		 * @param individualIndexChecks list of list of checks (where the inner list's checks are
		 *                              applied to each index of the collection parameter)
		 * @return this builder
		 */
		@SuppressWarnings("unchecked")
		public B setIndividualIndexChecks(List>> individualIndexChecks) {
			if (this.individualIndexChecks != null) {
				throw new IllegalArgumentException("Individual index checks has already been set.");
			}
			// could set to null if copying from another and wanting to remove it
			this.individualIndexChecks = individualIndexChecks;
			return (B) this;
		}

		/**
		 * Sets the {@link ApiMapParam} to be applied to each index of the collection.
		 * collection. This is used for collections of Maps.
		 *
		 * Either this or {@link #setIndividualIndexMapChecks(List)} can be set, but
		 * not both, because they would each return an {@link ApiMapParam.Result}
		 * where one would override the other.
		 *
		 * Either this or {@link #setInnerCollectionParam(ApiCollectionParam)} can be
		 * set, but not both.
		 *
		 * @param indexMapCheck the {@link ApiMapParam} to be used for each index
		 * @return
		 */
		@SuppressWarnings("unchecked")
		public B setIndexMapCheck(ApiMapParam indexMapCheck) {
			this.indexMapCheck = indexMapCheck;
			return (B) this;
		}

		/**
		 * Sets the {@link ApiMapParam} to be applied to a specific index of the
		 * collection. This is used for collections of Maps.
		 *
		 * Either this or {@link #setIndexMapCheck(ApiMapParam)} can be set, but
		 * not both, because they would each return an {@link ApiMapParam.Result}
		 * where one would override the other.
		 *
		 * Either this or {@link #setInnerCollectionParam(ApiCollectionParam)} can be
		 * set, but not both.
		 *
		 * @param individualIndexMapChecks the {@link ApiMapParam} to be used for a specific index
		 * @return
		 */
		@SuppressWarnings("unchecked")
		public B setIndividualIndexMapChecks(List individualIndexMapChecks) {
			this.individualIndexMapCheck = individualIndexMapChecks;
			return (B) this;
		}

		/**
		 * Sets the {@link ApiCollectionParam} used for a collection of collections (ad infinitum).
		 *
		 * Either this or {@link #setIndexMapCheck(ApiMapParam)} or {@link #setIndividualIndexMapChecks(List)}
		 * can be set, but not both.
		 *
		 * @param innerCollectionParam
		 * @return
		 */
		@SuppressWarnings("unchecked")
		public B setInnerCollectionParam(ApiCollectionParam innerCollectionParam) {
			if (innerCollectionParam.keyName != null) {
				throw new IllegalArgumentException("Cannot have inner array with a key name. If using an ApiCollectionParam " +
					                                   "that was created elsewhere, make a copy of it with the the builder.");
			}
			this.innerCollectionParam = innerCollectionParam;
			return (B) this;
		}

		/**
		 *
		 * @return
		 */
		protected abstract C buildImplementation();

		@Override
		public C build() {
			if (this.innerCollectionParam != null && this.innerCollectionParam.keyName != null) {
				throw new IllegalArgumentException("Cannot add inner array param that is named. Use builder to copy existing " +
					                                   "ApiCollectionParam if necessary.");
			}
			/*
			 * These cannot both be supplied since they both return values that would override each other.
			 * */
			if (this.indexMapCheck != null && listIsNotNullOrEmpty(this.individualIndexMapCheck)) {
				throw new IllegalArgumentException("Cannot set both indexMapChecks and individualIndexMapChecks.");
			}
			/*
			 * Cannot have inner array param set AND map checks. This is because the parameter is
			 * either a list or a map, but not both..
			 * */
			if ((this.indexMapCheck != null || listIsNotNullOrEmpty(this.individualIndexMapCheck)) &&
				this.innerCollectionParam != null) {
				throw new IllegalArgumentException("Cannot set both index map check and inner array param.");
			}
			/*
			 * Cannot create without checks for innermost array/list.
			 * */
			if (this.innerCollectionParam == null &&
				!listIsNotNullOrEmpty(this.indexChecks) &&
				!listIsNotNullOrEmpty(this.individualIndexChecks) &&
				indexMapCheck == null &&
				!listIsNotNullOrEmpty(this.individualIndexMapCheck)) {
				throw new IllegalArgumentException("Cannot create ApiCollectionParam with no checks and no inner array. Use " +
					                                   "an always pass check if this is desired.");
			}
			return buildImplementation();
		}

	}

	/*
	 *
	 * IMPLEMENTATION
	 *
	 * */

	@SuppressWarnings("unchecked")
	protected ApiCollectionParam(Builder builder) {
		super(builder);
		this.collectionChecks = getArrayIfNotNullOrEmpty(builder.collectionChecks, new Check[0]);
		this.indexChecks = getArrayIfNotNullOrEmpty(builder.indexChecks, new CollectionIndexCheck[0]);
		this.individualIndexChecks = listIsNotNullOrEmpty(builder.individualIndexChecks)
			?
			builder
				.individualIndexChecks
				.stream()
				.[]>>collect(
					ArrayList::new,
					(collectionList, listOfArrayChecks) ->
						collectionList.add(listOfArrayChecks.toArray(new CollectionIndexCheck[0])),
					List::addAll
				)
				.toArray(new CollectionIndexCheck[0][])
			:
			null;
		this.indexMapCheck = builder.indexMapCheck;
		this.individualIndexMapChecks = listIsNotNullOrEmpty(builder.individualIndexMapCheck)
			?
			builder.individualIndexMapCheck.toArray(new ApiMapParam[0])
			:
			null;
		this.innerCollectionParam = builder.innerCollectionParam;
	}


	/**
	 * Wraps the error and provides the index where the error occurred.
	 * @param index
	 * @param apiParamError
	 * @return a failed parameter result
	 */
	private Result returnFailedCheckResult(int index, ApiParamError apiParamError) {
		return Result.failure(new ApiParamError(this.keyName,
		                                        this.displayName,
		                                        apiParamError.errorType,
		                                        apiParamError.errorMessage,
		                                        apiParamError.exception,
		                                        index,
		                                        apiParamError));
	}

	protected abstract int getCollectionSize(Collection paramCollection);

	protected abstract Param getParamAtIndex(int i, Collection paramCollection);

	@SuppressWarnings("unchecked")
	@Override
	public Result check(In params) {
		try {
			/*
			 * params argument can be either a Map or an Array/List (for nested arrays).
			 * The topmost level will be a Map, but if this is a nested ApiArrayParam it
			 * will be an Array/List.
			 * */
			Collection collectionParam;
			if (this.keyName != null) {
				if (!(params instanceof Map)) {
					return Result.failure(new ApiParamError(this.keyName,
					                                        this.displayName,
					                                        ApiErrorType.CASTING_ERROR,
					                                        "Casting error."));
				}
				collectionParam = (Collection) ((Map) params).get(this.keyName);
			} else {
				// If there is no key name then this must be a list (and this is likely an innerArrayParam)
				collectionParam = (Collection) params;
			}

			if (collectionParam == null) {
				if (this.canBeNull) {
					return Result.success(this.keyName);
				} else {
					return Result.failure(ApiParamError.missing(this.keyName, this.displayName));
				}
			}

			/*
			 * In the interest of reducing redundancy need to get the length here so that
			 * it can be used throughout the checks below. Otherwise would need to have a
			 * branch of type Array and a branch for type List. The method getParamAtIndex()
			 * is also supplied to complement this. Now, only one branch of code is necessary
			 * to handle an array or list.
			 * */
			int collectionLength = getCollectionSize(collectionParam);

			if (this.collectionChecks != null) {
				for (Check check : this.collectionChecks) {
					Check.Result checkResult = check.check(collectionParam);
					if (checkResult.failed()) {
						return Result.failure(new ApiParamError(this.keyName,
						                                        this.displayName,
						                                        ApiErrorType.INVALID_PARAMETER,
						                                        checkResult.failureMessage));
					}
				}
			}

			/*
			 * Checks can be run at any level, though it is likely they will be null for
			 * all levels except the most inner array.
			 *
			 * Checks only return successful or a failure message. If they are successful
			 * just continue on, otherwise return the (possibly null) failure message with
			 * an invalid parameter check.
			 * */
			if (this.indexChecks != null && this.indexChecks.length > 0) {
				for (int i = 0; i < collectionLength; i++) {
					Param paramToCheck = getParamAtIndex(i, collectionParam);
					for (int j = 0; j < this.indexChecks.length; j++) {
						Check.Result checkResult = this.indexChecks[j].check(i, paramToCheck);
						if (checkResult.failed()) {
							return Result.failure(new ApiParamError(this.keyName,
							                                        this.displayName,
							                                        ApiErrorType.INVALID_PARAMETER,
							                                        checkResult.failureMessage,
							                                        null,
							                                        i,
							                                        null));
						}
					}
				}
			}

			// check at each position
			if (this.individualIndexChecks != null && this.individualIndexChecks.length > 0) {
				if (this.individualIndexChecks.length != collectionLength) {
					return Result.failure(ApiParamError.invalid(this, "List of incorrect size. Should be " +
						this.individualIndexChecks.length));
				}
				for (int i = 0; i < this.individualIndexChecks.length; i++) {
					CollectionIndexCheck[] indexChecks = this.individualIndexChecks[i];
					if (indexChecks != null && indexChecks.length > 0) {
						Param paramToCheck = getParamAtIndex(i, collectionParam);
						for (int j = 0; j < indexChecks.length; j++) {
							Check.Result checkResult = indexChecks[j].check(i, paramToCheck);
							if (checkResult.failed()) {
								return Result.failure(new ApiParamError(this.keyName,
								                                        this.displayName,
								                                        ApiErrorType.INVALID_PARAMETER,
								                                        checkResult.failureMessage,
								                                        null,
								                                        i,
								                                        null));
							}
						}
					}
				}
			}

			/*
			 * Map checks can only be run when there is no innerArrayParam supplied. This
			 * is guaranteed by the constructor. So if/else works fine here. If an inner
			 * array is supplied AND it returns
			 * */
			if (this.innerCollectionParam != null) {
				/*
				 * Need to keep all returned check results at first, because some may return null
				 * while others may return something of interest. If only kept the ones that were
				 * of interest then the positions would be off.
				 * */
				List innerArrayCheckResults = new ArrayList<>(collectionLength);
				// only want to add to these if the returned
				for (int i = 0; i < collectionLength; i++) {
					Param param = getParamAtIndex(i, collectionParam);
					if (!(param instanceof List) && !(param instanceof Object[])) {
						return Result.failure(new ApiParamError(this.keyName,
						                                        this.displayName,
						                                        ApiErrorType.INVALID_PARAMETER,
						                                        "Not a list or array.",
						                                        null,
						                                        i,
						                                        null));
					}
					Result checkResult = this.innerCollectionParam.check(param);
					if (checkResult.failed()) {
						return returnFailedCheckResult(i, checkResult.error);
					}
					// only want to keep check result if it has fields set... should not have any named fields
					innerArrayCheckResults.add(checkResult);
				}
				/*
				 * Go through inner array check results. If any one has inner arrays or maps
				 * then need to return them all, otherwise just return success.
				 * */
				for (Result res : innerArrayCheckResults) {
					if (res.hasInnerCollectionResults() || res.hasMapResults()) {
						return Result.successWithNestedList(this.keyName, innerArrayCheckResults);
					}
				}
				return Result.success(this.keyName);
			} else if (this.indexMapCheck != null) {
				List indexMapCheckResults = new ArrayList<>(collectionLength);
				for (int i = 0; i < collectionLength; i++) {
					ApiMapParam.Result mapCheckResult =
						this.indexMapCheck.check((Map) getParamAtIndex(i, collectionParam));
					if (mapCheckResult.failed()) {
						return returnFailedCheckResult(i, mapCheckResult.error);
					}
					// successful, add it
					indexMapCheckResults.add(mapCheckResult);
				}
				return Result.successWithMapCheckResults(this.keyName, indexMapCheckResults);
			} else if (this.individualIndexMapChecks != null && this.individualIndexMapChecks.length > 0) {
				if (this.individualIndexMapChecks.length != collectionLength) {
					return Result.failure(
						ApiParamError.invalid(this,
						                      "List of incorrect size. Should be size "
							                      + this.individualIndexMapChecks.length + ".")
					);
				}
				List indexMapCheckResults = new ArrayList<>(collectionLength);
				for (int i = 0; i < this.individualIndexMapChecks.length; i++) {
					// must be of map type
					ApiMapParam.Result mapCheckResult =
						this.individualIndexMapChecks[i].check((Map) getParamAtIndex(i, collectionParam));
					if (mapCheckResult.failed()) {
						return returnFailedCheckResult(i, mapCheckResult.error);
					}
					indexMapCheckResults.add(mapCheckResult);
				}
				return Result.successWithMapCheckResults(this.keyName, indexMapCheckResults);
			}
			/*
			 * There are no inner array checks or index map checks, therefore this must
			 * be simply checking an array (potentially nested). This is usually not
			 * recommended as {@link io.github.bhowell2.apilib.checks.ArrayChecks} with
			 * a {@link ApiSingleParam} will work just as well, but this allows for more
			 * nesting than the standard structure.
			 * */
			return Result.success(this.keyName);
		} catch (ClassCastException e) {
			return Result.failure(ApiParamError.cast(this, e));
		} catch (Exception e) {
			return Result.failure(ApiParamError.exceptional(this, e));
		}
	}

	/*
	 *
	 * RESULT
	 *
	 * */

	/**
	 * Result from checking an {@link ApiCollectionParam}.
	 */
	public static class Result extends ApiParamBase.Result {
		/**
		 * Used to return the results of array checks within this
		 * array check. This will be used in the (very) rare case
		 * that an array of arrays (of arrays...) of maps is a
		 * parameter.
		 */
		public final List innerCollectionResults;

		/**
		 * Used to return ApiMapParam.Result for each position in an
		 * array. If an array of arrays of maps is a parameter this
		 * will be null for the outermost array while
		 * {@link #innerCollectionResults} will be set in the outermost
		 * array and the innermost array will have this set while
		 * {@link #innerCollectionResults} will be null.
		 *
		 * Take the following example (JSON):
		 * 
		 *  {@code
		 * 	 {
		 * 	  array: [
		 * 	     // 1st array within array
		 * 	     [
		 * 	       {
		 * 	         param1: "passing",
		 * 	         param2: "passing"
		 * 	       },
		 * 	       {
		 * 	         param1: "passing"
		 * 	       }
		 * 	     ],
		 * 	     // 2nd array within array
		 * 	     [
		 * 	       {
		 * 	         param2: "passing"
		 * 	       }
		 * 	     ]
		 * 	  ]
		 * 	 }
		 * 	}
		 * 
* Will return the following Result (JSON): *
		 *   {@code
		 *    {
		 *      keyName: "some key name"
		 *      mapCheckResults: null,
		 *      innerCollectionCheckResults: [
		 *        // 1st inner array check result
		 *        {
		 *          keyName: null,
		 *          innerCollectionCheckResults: null,
		 *          mapCheckResults: [
		 *            {
		 *              checkedKeyNames: ["param1", "param2"]
		 *            },
		 *            {
		 *              checkedKeyNames: ["param1"]
		 *            }
		 *          ]
		 *        },
		 *        // 2nd inner array check result
		 *        {
		 *          keyName: null,
		 *          innerCollectionCheckResults: null,
		 *          mapCheckResults: [
		 *            {
		 *              checkedKeyNames: ["param2"]
		 *            }
		 *          ]
		 *        }
		 *      ]
		 *    }
		 *   }
		 * 
* */ public final List mapResults; public Result(String keyName, List innerCollectionResults, List mapResults) { super(keyName); this.innerCollectionResults = innerCollectionResults; this.mapResults = mapResults; } public Result(ApiParamError error) { super(error); this.innerCollectionResults = null; this.mapResults = null; } public boolean hasInnerCollectionResults() { return this.innerCollectionResults != null; } /** * Whether or not there are resulting {@link ApiParamBase.Result}s for each index * of the collection. The user would have set {@link #indexMapCheck} or * {@link #individualIndexChecks}. */ public boolean hasMapResults() { return this.mapResults != null; } /* Static Creation Methods */ /** * Used when only the values of the list are checked and there are * no {@link ApiMapParam.Result}s to return at any level of the the * array/list. * * @param keyName name of successfully checked list/array parameter * @return successful param result */ public static Result success(String keyName) { return new Result(keyName, null, null); } /** * Used when an array/list is nested within another and the innermost * array/list needs to return {@link ApiMapParam}s. @param keyName currently allowing keyName, but it doesn't strictly make sense as there are * no keyNames for the index positions. the position in the list is the index * of each result as it is * @param innerCollectionResults result for check of (inner) collection at each index of collection * @return successful param result */ public static Result successWithNestedList(String keyName, List innerCollectionResults) { return new Result(keyName, innerCollectionResults, null); } /** * @param keyName currently allowing keyName, but it doesn't strictly make sense as there are * no keyNames for the index positions. the position in the list is the index * of each result as it is * @param mapResults result for check of map at each index of collection * @return successful param result */ public static Result successWithMapCheckResults(String keyName, List mapResults) { return new Result(keyName, null, mapResults); } public static Result failure(ApiParamError error) { return new Result(error); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy