Validator
A general-purpose validation suite with two complementary families:
predicate validators that never throw (returning
false for input that can't satisfy a rule), and
contract validators (require*) that enforce a
precondition and throw a descriptive exception when violated.
Una suite de validación de propósito general con dos familias complementarias:
validadores de predicado que nunca lanzan (devolviendo
false ante entrada que no puede satisfacer una regla), y
validadores de contrato (require*) que imponen
una precondición y lanzan una excepción descriptiva cuando se viola.
Two families, two intentionsDos familias, dos intenciones
- Predicates (
isBlank,isEmail,isInRange, …) — fully null-safe, composable in UI bindings, guard clauses and business logic. They answer "is this valid?" without side effects.Predicados (isBlank,isEmail,isInRange, …) — totalmente null-safe, componibles en bindings de UI, cláusulas de guarda y lógica de negocio. Responden "¿esto es válido?" sin efectos secundarios. - Contracts (
requireNotBlank,requireInRange, …) — enforce a precondition and return the value when valid, throwing otherwise. They answer "this must be valid — fail loudly if not."Contratos (requireNotBlank,requireInRange, …) — imponen una precondición y devuelven el valor cuando es válido, lanzando excepción en caso contrario. Responden "esto debe ser válido — falla ruidosamente si no lo es."
Every regex is a pre-compiled, immutable Pattern written in linear (non-backtracking) form, so even hostile input can't trigger catastrophic backtracking. All methods are stateless and thread-safe.Cada regex es un Pattern inmutable y precompilado, escrito en forma lineal (sin backtracking), así que ni la entrada hostil puede provocar backtracking catastrófico. Todos los métodos son sin estado y thread-safe.
Quick startInicio rápido
Validator v = Validator.getInstance();
// Predicates — never throw:
if (v.isBlank(name)) { /* show "required" */ }
if (!v.isEmail(email)) { /* show "bad e-mail" */ }
if (v.isInRange(age, 18, 120)) { /* ok */ }
// Contracts — throw on violation, return the value on success:
String n = v.requireNotBlank(name, "name");
int qty = (int) v.requireInRange(quantity, 1, 99, "quantity");
Null & presence predicatesPredicados de null y presencia
| MethodMétodo | Returns true when…Devuelve true cuando… |
|---|---|
isNull(Object) / isNotNull(Object) | the reference is / isn't null.la referencia es / no es null. |
isEmpty(String) / isNotEmpty(String) | the string is null-or-empty / has ≥ 1 char.la cadena es null-o-vacía / tiene ≥ 1 carácter. |
isBlank(String) / isNotBlank(String) | the string is null/empty/whitespace / has a non-whitespace char.la cadena es null/vacía/espacios / tiene un carácter no en blanco. |
Length predicatesPredicados de longitud
| MethodMétodo | Checks (on the trimmed length)Comprueba (sobre la longitud recortada) |
|---|---|
hasMinLength(s, min) | length ≥ min (false if null).longitud ≥ min (false si null). |
hasMaxLength(s, max) | length ≤ max (false if null).longitud ≤ max (false si null). |
hasLengthBetween(s, min, max) | length within [min, max] (false if null).longitud dentro de [min, max] (false si null). |
Text / format predicatesPredicados de texto / formato
| MethodMétodo | MatchesCoincide con |
|---|---|
isNumeric(s) | digits only (non-negative integer), trimmed.solo dígitos (entero no negativo), recortado. |
isInteger(s) | optionally signed integer, trimmed.entero con signo opcional, recortado. |
isDecimal(s) | optionally signed decimal, trimmed.decimal con signo opcional, recortado. |
isAlphabetic(s) | Unicode letters only.solo letras Unicode. |
isAlphabeticWithSpaces(s) | letters with single spaces between words (no leading/trailing/double spaces).letras con espacios simples entre palabras (sin espacios al inicio/final/dobles). |
isAlphanumeric(s) | Unicode letters and digits.letras y dígitos Unicode. |
isEmail(s) | a pragmatic, RFC-ish e-mail (trimmed, linear-time).un e-mail pragmático, estilo RFC (recortado, tiempo lineal). |
matches(s, String regex) | full match; returns false (never throws) on null args or invalid regex.coincidencia completa; devuelve false (nunca lanza) ante args null o regex inválida. |
matches(s, Pattern) | full match against a pre-compiled pattern.coincidencia completa contra un patrón precompilado. |
Numeric range & signRango numérico y signo
| MethodMétodo | NotesNotas |
|---|---|
isInRange(long value, long min, long max) | Inclusive; bounds auto-normalized (order doesn't matter).Inclusivo; los límites se normalizan automáticamente (el orden no importa). |
isInRange(double value, double min, double max) | Inclusive, normalized; NaN is never in range.Inclusivo, normalizado; NaN nunca está en rango. |
isPositive(Number) · isNegative(Number) · isNonNegative(Number) | Strict > 0, strict < 0, ≥ 0; false for null.Estricto > 0, estricto < 0, ≥ 0; false para null. |
Collection / map / array predicatesPredicados de colección / mapa / array
Overloaded isEmpty / isNotEmpty for Collection<?>, Map<?,?> and Object[] — all null-safe (a null container counts as empty).Sobrecargas de isEmpty / isNotEmpty para Collection<?>, Map<?,?> y Object[] — todas null-safe (un contenedor null cuenta como vacío).
Contract validators (throwing)Validadores de contrato (lanzan)
Returns value or throws NullPointerException(message).Devuelve value o lanza NullPointerException(message).
Returns the original (untrimmed) value, or throws IllegalArgumentException ("name cannot be null or blank").Devuelve el valor original (sin recortar), o lanza IllegalArgumentException ("name cannot be null or blank").
Returns value if within [min, max] (normalized), else throws IllegalArgumentException with a message naming the value and bounds.Devuelve value si está dentro de [min, max] (normalizado), de lo contrario lanza IllegalArgumentException con un mensaje que nombra el valor y los límites.
Same for doubles; NaN is never in range and always fails.Igual para doubles; NaN nunca está en rango y siempre falla.
Validate with predicates, then report with Answer:Valida con predicados y luego reporta con Answer:
if (!v.isEmail(email)) return Answer.failure("Please enter a valid e-mail");
return Answer.success("Account created").with("userId", id);
Use predicates for user-facing validation where you'll render a friendly message; use contracts at API boundaries where invalid input is a programming error that should fail fast. Don't wrap require* in a try/catch for normal UI validation — that's what the predicates are for.Usa predicados para validación de cara al usuario donde mostrarás un mensaje amable; usa contratos en los límites de la API donde la entrada inválida es un error de programación que debe fallar rápido. No envuelvas require* en un try/catch para la validación normal de UI — para eso están los predicados.
RecommendationsRecomendaciones
Combine with Format: the formatter restricts keystrokes; the validator confirms the final value (range, e-mail, length).Combina con Format: el formateador restringe las pulsaciones; el validador confirma el valor final (rango, e-mail, longitud).
Lean on null-safety — pass possibly-null fields straight to predicates without guarding; they handle null for you.Apóyate en el null-safety — pasa campos posiblemente null directamente a los predicados sin proteger; ellos manejan null por ti.