io.inversion.Validation Maven / Gradle / Ivy
The newest version!
/*
* Copyright (c) 2015-2022 Rocket Partners, LLC
* https://github.com/inversion-api
*
* 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 io.inversion;
import io.inversion.json.JSList;
import io.inversion.json.JSNode;
import io.inversion.json.JSParser;
import io.inversion.utils.Utils;
import java.util.regex.Pattern;
/**
* Utility designed to make it easy to validate request properties or request body
* json values while you are retrieving them.
*/
public class Validation {
final String customErrorMessage;
final String propOrPath;
Object value;
public Validation(Request req, String propOrPath, String customErrorMessage) {
value = req.getUrl().getParam(propOrPath);
if (value == null && req.getJson() != null)
value = req.getJson().find(propOrPath);
this.propOrPath = null;
this.customErrorMessage = customErrorMessage;
}
public Validation(Response res, String jsonPath, String customErrorMessage) {
this.value = res.find(jsonPath);
this.propOrPath = null;
this.customErrorMessage = customErrorMessage;
}
/**
* If there are any childProps
they must exist on the JSNode
* found at pathOrProp
. If childProps
are null/empty
* then pathOrProp
must not be null.
*
* @param childProps the child properties to check for
* @return this
* @throws ApiException 400 if the referenced validation is null.
*/
public Validation required(String... childProps) {
if (Utils.empty(value))
fail("Required field '" + propOrPath + "' is missing.");
if (childProps != null && value instanceof JSNode && !((JSNode) value).isList()) {
for (String childProp : childProps) {
if (Utils.empty(((JSNode) value).get(childProp))) {
fail("Required field '" + propOrPath + "." + childProp + "' is missing.");
}
}
}
return this;
}
public Validation matches(Pattern regex) {
if (value == null || !regex.matcher(value.toString()).matches())
fail("Field '" + propOrPath + "' does not match the required pattern.");
return this;
}
public Validation matches(String regex) {
if (value == null)
return this;
if (!value.toString().matches(regex))
fail("Field '" + propOrPath + "' does not match the required pattern.");
return this;
}
public Validation in(Object... possibleValues) {
if (value == null)
return this;
if (!Utils.in(value, possibleValues))
fail("Field '" + propOrPath + "' is not one of the possible values.");
return this;
}
public Validation out(Object... excludedValues) {
if (value == null)
return this;
if (Utils.in(value, excludedValues))
fail("Field '" + propOrPath + "' has a restricted value.");
return this;
}
protected int compareTo(Object compareTo) {
Object value = this.value;
if (compareTo instanceof Number) {
try {
value = Double.parseDouble(value.toString());
compareTo = Double.parseDouble(compareTo.toString());
} catch (Exception ex) {
//ignore numeric type conversion error.
}
}
if (value instanceof Comparable)
return ((Comparable) value).compareTo(compareTo);
return (value + "").compareTo(compareTo + "");
}
public Validation gt(Object compareTo) {
if (value == null)
return this;
if (compareTo(compareTo) < 1)
fail("Field '" + propOrPath + "' is less than the required value.");
return this;
}
public Validation ge(Object compareTo) {
if (value == null)
return this;
if (compareTo(compareTo) < 0)
fail("Field '" + propOrPath + "' is less than the required value.");
return this;
}
public Validation lt(Object compareTo) {
if (value == null)
return this;
if (compareTo(compareTo) > -1)
fail("Field '" + propOrPath + "' is greater than the required value.");
return this;
}
public Validation le(Object compareTo) {
if (value == null)
return this;
if (compareTo(compareTo) > 0)
fail("Field '" + propOrPath + "' is greater than the required value.");
return this;
}
public Validation eq(Object compareTo) {
if (value == null)
return this;
if (compareTo(compareTo) != 0)
fail("Field '" + propOrPath + "' is not equal to the required value.");
return this;
}
public Validation ne(Object compareTo) {
if (value == null)
return this;
if (compareTo(compareTo) != 0)
fail("Field '" + propOrPath + "' is equal to a restricted value.");
return this;
}
public Validation length(int max) {
if (value == null)
return this;
if (value.toString().length() > max)
fail("Field '" + propOrPath + "' is longer than the max allowed length of '" + max + "'.");
return this;
}
public Validation length(int min, int max) {
if (value == null)
return this;
int length = value.toString().length();
if (length > max)
fail("Field '" + propOrPath + "' is longer than the maximum allowed length of '" + max + "'.");
if (length < min)
fail("Field '" + propOrPath + "' is shorter than the minimum allowed length of '" + max + "'.");
return this;
}
public Validation minMax(Number min, Number max) {
if (value == null)
return this;
max(max);
min(min);
return this;
}
public Validation max(Number max) {
if (value == null)
return this;
if (Double.parseDouble(max.toString()) < Double.parseDouble(value.toString()))
fail("Field '" + propOrPath + "' is greater than the required maximum of '" + max + "'.");
return this;
}
public Validation min(Number min) {
if (value == null)
return this;
if (Double.parseDouble(min.toString()) > Double.parseDouble(value.toString()))
fail("Field '" + propOrPath + "' is less than the required minimum of '" + min + "'.");
return this;
}
public Object value() {
return value;
}
public JSNode asNode() {
if (value == null)
return null;
if (value instanceof String)
value = JSParser.parseJson(value.toString());
return ((JSNode) value);
}
public JSList asArray() {
if (value == null)
return null;
if (value instanceof String)
value = JSParser.asJSList(value.toString());
return ((JSList) value);
}
public String asString() {
if (value == null)
return null;
return value.toString();
}
public int asInt() {
if (value == null)
return -1;
try {
return Integer.parseInt(value + "");
} catch (Exception ex) {
fail("Field '" + propOrPath + "' must be an integer.");
}
return -1;
}
public double asDouble() {
if (value == null)
return -1;
try {
return Double.parseDouble(value + "");
} catch (Exception ex) {
fail("Field '" + propOrPath + "' must be an number.");
}
return -1;
}
public boolean asBoolean() {
try {
return Boolean.parseBoolean(value + "");
} catch (Exception ex) {
fail("Field '" + propOrPath + "' must be a boolean.");
}
return false;
}
/**
* Throws an ApiException 400 using customErrorMessage or defaultErrorMessage
*
* @param defaultErrorMessage the default error message
* @throws ApiException always
*/
protected void fail(String defaultErrorMessage) throws ApiException {
String message = customErrorMessage != null ? customErrorMessage : defaultErrorMessage;
throw ApiException.new400BadRequest(message);
}
}