@@ -61,29 +61,22 @@ public Stream<String> imports() {
6161
6262 @ Override
6363 public void writePropertiesTo (ValidationOutput out ) {
64- String fieldName = constantName (out .getVariable ());
6564 switch (kind ) {
6665 case BIG_DECIMAL , NUMBER , CHAR_SEQUENCE -> out .write ("""
6766 private static final BigDecimal %s = new BigDecimal("%s");
68- """ .formatted (fieldName , value ));
67+ """ .formatted (constantName ( out . getVariable ()) , value ));
6968 case BIG_INTEGER -> out .write ("""
7069 private static final BigInteger %s = new BigInteger("%s");
71- """ .formatted (fieldName , value ));
70+ """ .formatted (constantName ( out . getVariable ()) , value ));
7271 case BYTE , SHORT , INTEGER , LONG , DOUBLE , FLOAT -> { /* primitives: no caching needed */ }
7372 }
7473 }
7574
7675 @ Override
7776 public void writeBodyTo (ValidationOutput out ) {
78- String fieldName = constantName (out .getVariable ());
79- String comparison = switch (kind ) {
80- case BIG_DECIMAL , BIG_INTEGER -> "%s.compareTo(%s) %s 0" .formatted (out .getVariable (), fieldName , operator );
81- case BYTE , SHORT , INTEGER , LONG , DOUBLE , FLOAT -> "%s %s %s" .formatted (out .getVariable (), operator , value );
82- case NUMBER , CHAR_SEQUENCE -> "new BigDecimal(%s.toString()).compareTo(%s) %s 0" .formatted (out .getVariable (), fieldName , operator );
83- };
8477 out .write ("""
8578 if (!(%s)) {\
86- """ .formatted (comparison ));
79+ """ .formatted (comparison ( out ) ));
8780 out .incrementIndentationLevel ();
8881 out .write ("""
8982 validation.addError("%s"%s);\
@@ -92,13 +85,24 @@ public void writeBodyTo(ValidationOutput out) {
9285 out .write ("}" );
9386 }
9487
88+ private String comparison (ValidationOutput out ) {
89+ return switch (kind ) {
90+ case BIG_DECIMAL , BIG_INTEGER -> "%s.compareTo(%s) %s 0" .formatted (
91+ out .getVariable (), constantName (out .getVariable ()), operator );
92+ case BYTE , SHORT , INTEGER , LONG , DOUBLE , FLOAT -> "%s %s %s" .formatted (
93+ out .getVariable (), operator , value );
94+ case NUMBER , CHAR_SEQUENCE -> "new BigDecimal(%s.toString()).compareTo(%s) %s 0" .formatted (
95+ out .getVariable (), constantName (out .getVariable ()), operator );
96+ };
97+ }
98+
9599 private String constantName (String variable ) {
96100 String opSuffix = switch (operator ) {
97101 case ">=" -> "GE" ;
98102 case ">" -> "GT" ;
99103 case "<=" -> "LE" ;
100104 case "<" -> "LT" ;
101- default -> operator ;
105+ default -> operator ;
102106 };
103107 String valueSuffix = value .toString ().replace ("-" , "N" ).replace ("." , "_" );
104108 return variable .toUpperCase () + "_" + opSuffix + "_" + valueSuffix ;
@@ -140,9 +144,15 @@ public Stream<String> imports() {
140144
141145 @ Override
142146 public void writeBodyTo (ValidationOutput out ) {
143- out .write ("""
144- if (!(%s.%s(%s) == %s)) {\
145- """ .formatted (normalized (out .getVariable ()), accessor , now (), result ));
147+ if (result ) {
148+ out .write ("""
149+ if (!%s.%s(%s)) {\
150+ """ .formatted (normalized (out .getVariable ()), accessor , now ()));
151+ } else {
152+ out .write ("""
153+ if (%s.%s(%s)) {\
154+ """ .formatted (normalized (out .getVariable ()), accessor , now ()));
155+ }
146156 out .incrementIndentationLevel ();
147157 out .write ("""
148158 validation.addError("%s");\
@@ -182,19 +192,17 @@ private String normalized(String variable) {
182192 }
183193 }
184194
185- String EMAIL_REGEX = "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\ \\ .[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$" ;
186-
187195 record EmailPattern (@ Nullable String regexp , List <String > flags , String message ) implements NullUnsafeWriter {
188196 @ Override
189197 public Stream <String > imports () {
190- return Stream .of ("java.util.regex.Pattern" );
198+ return Stream .concat (
199+ Stream .of ("io.github.raniagus.javalidation.validator.Predicates" ),
200+ regexp != null ? Stream .of ("java.util.regex.Pattern" ) : Stream .empty ()
201+ );
191202 }
192203
193204 @ Override
194205 public void writePropertiesTo (ValidationOutput out ) {
195- out .write ("""
196- private static final Pattern %s_EMAIL_PATTERN = Pattern.compile("%s");
197- """ .formatted (out .getVariable ().toUpperCase (), EMAIL_REGEX ));
198206 if (regexp != null ) {
199207 out .write ("""
200208 private static final Pattern %1$s_REGEXP_PATTERN = Pattern.compile("%2$s"%3$s);
@@ -206,12 +214,11 @@ public void writePropertiesTo(ValidationOutput out) {
206214 public void writeBodyTo (ValidationOutput out ) {
207215 if (regexp == null ) {
208216 out .write ("""
209- if (!%s_EMAIL_PATTERN.matcher (%s.toString()).matches( )) {\
210- """ .formatted (out .getVariable (). toUpperCase (), out . getVariable () ));
217+ if (!Predicates.isEmail (%s)) {\
218+ """ .formatted (out .getVariable ()));
211219 } else {
212220 out .write ("""
213- if (!%1$s_EMAIL_PATTERN.matcher(%2$s.toString()).matches()
214- || !%1$s_REGEXP_PATTERN.matcher(%2$s.toString()).matches()) {\
221+ if (!Predicates.isEmail(%2$s) || !%1$s_REGEXP_PATTERN.matcher(%2$s).matches()) {\
215222 """ .formatted (out .getVariable ().toUpperCase (), out .getVariable ()));
216223 }
217224 out .incrementIndentationLevel ();
@@ -282,40 +289,49 @@ record Digits(
282289 @ Override
283290 public Stream <String > imports () {
284291 return switch (kind ) {
285- case CHAR_SEQUENCE -> Stream .of ("java.util.regex.Pattern" );
286- case BIG_DECIMAL -> Stream .empty ();
287- case BIG_INTEGER , NUMBER , BYTE , SHORT , INTEGER , LONG , DOUBLE , FLOAT -> Stream .of ("java.math.BigDecimal" );
292+ case CHAR_SEQUENCE -> Stream .of ("io.github.raniagus.javalidation.validator.Predicates" , "java.util.function.Predicate" );
293+ case BIG_INTEGER , NUMBER , BYTE , SHORT , INTEGER , LONG , DOUBLE , FLOAT -> Stream .of (
294+ "io.github.raniagus.javalidation.validator.Predicates" ,
295+ "java.math.BigDecimal"
296+ );
297+ case BIG_DECIMAL -> Stream .of ("io.github.raniagus.javalidation.validator.Predicates" );
288298 };
289299 }
290300
291301 @ Override
292302 public void writePropertiesTo (ValidationOutput out ) {
293- if (kind == NumericKind .CHAR_SEQUENCE ) {
294- String pattern = "^-?\\ \\ d{0," + integer + "}(\\ \\ .\\ \\ d{0," + fraction + "})?$" ;
295- out .write ("""
296- private static final Pattern %s_DIGITS_PATTERN = Pattern.compile("%s");
297- """ .formatted (out .getVariable ().toUpperCase (), pattern ));
303+ switch (kind ) {
304+ case CHAR_SEQUENCE ->
305+ out .write ("""
306+ private static final Predicate<CharSequence> %s_DIGITS_PREDICATE = Predicates.digits(%d, %d);
307+ """ .formatted (out .getVariable ().toUpperCase (), integer , fraction ));
308+ case BIG_INTEGER , NUMBER , BYTE , SHORT , INTEGER , LONG , DOUBLE , FLOAT , BIG_DECIMAL -> {
309+ // No Predicate to precompile
310+ }
298311 }
299312 }
300313
301314 @ Override
302315 public void writeBodyTo (ValidationOutput out ) {
303- if (kind == NumericKind .CHAR_SEQUENCE ) {
304- out .write ("""
305- if (!%s_DIGITS_PATTERN.matcher(%s.toString()).matches()) {\
306- """ .formatted (out .getVariable ().toUpperCase (), out .getVariable ()));
307- } else {
308- String bdExpr = switch (kind ) {
309- case CHAR_SEQUENCE -> throw new IllegalStateException ("CHAR_SEQUENCE should be handled separately" );
310- case BIG_DECIMAL -> "%s.stripTrailingZeros()" .formatted (out .getVariable ());
311- case BIG_INTEGER , NUMBER -> "new BigDecimal(%s.toString()).stripTrailingZeros()" .formatted (out .getVariable ());
312- case BYTE , SHORT , INTEGER , LONG , DOUBLE , FLOAT -> "BigDecimal.valueOf(%s)" .formatted (out .getVariable ());
313- };
314- out .write ("var %s_bd = %s;" .formatted (out .getVariable (), bdExpr ));
315- out .write ("""
316- if (!(%1$s_bd.precision() - %1$s_bd.scale() <= %2$s && Math.max(%1$s_bd.scale(), 0) <= %3$s)) {\
317- """ .formatted (out .getVariable (), integer , fraction ));
316+ switch (kind ) {
317+ case CHAR_SEQUENCE ->
318+ out .write ("""
319+ if (!%s_DIGITS_PREDICATE.test(%s)) {\
320+ """ .formatted (out .getVariable ().toUpperCase (), out .getVariable ()));
321+ case BIG_INTEGER , NUMBER ->
322+ out .write ("""
323+ if (!Predicates.digits(new BigDecimal(%s.toString()), %d, %d)) {\
324+ """ .formatted (out .getVariable (), integer , fraction ));
325+ case BYTE , SHORT , INTEGER , LONG , DOUBLE , FLOAT ->
326+ out .write ("""
327+ if (!Predicates.digits(BigDecimal.valueOf(%s), %d, %d)) {\
328+ """ .formatted (out .getVariable (), integer , fraction ));
329+ case BIG_DECIMAL ->
330+ out .write ("""
331+ if (!Predicates.digits(%s, %d, %d)) {\
332+ """ .formatted (out .getVariable (), integer , fraction ));
318333 }
334+
319335 out .incrementIndentationLevel ();
320336 out .write ("""
321337 validation.addError("%s", %s, %s);\
0 commit comments