You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@causeway.apache.org by ah...@apache.org on 2026/06/24 15:49:14 UTC
(causeway) branch main updated: CAUSEWAY-4036: validate digit count constraints
This is an automated email from the ASF dual-hosted git repository.
andi-huber pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/causeway.git
The following commit(s) were added to refs/heads/main by this push:
new 5408d140ce5 CAUSEWAY-4036: validate digit count constraints
5408d140ce5 is described below
commit 5408d140ce53d640b10cee9b99d5b1001bc3664f
Author: ahuber@apache.org <ah...@192.168.0.235>
AuthorDate: Wed Jun 24 17:49:03 2026 +0200
CAUSEWAY-4036: validate digit count constraints
---
.../NumericValueSemanticsAbstract.java | 61 ++++++++++++++++------
1 file changed, 46 insertions(+), 15 deletions(-)
diff --git a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/NumericValueSemanticsAbstract.java b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/NumericValueSemanticsAbstract.java
index bab9b79d6db..ac9ffd97caa 100644
--- a/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/NumericValueSemanticsAbstract.java
+++ b/core/metamodel/src/main/java/org/apache/causeway/core/metamodel/valuesemantics/NumericValueSemanticsAbstract.java
@@ -69,7 +69,7 @@ public String htmlPresentation(final Context context, final T value) {
@Override
public final String parseableTextRepresentation(final Context context, final T value) {
return value!=null
- ? getNumberFormat(context, FormatUsageFor.PARSING).format(value)
+ ? getNumberFormat(context, FormatUsageFor.RENDERING_AS_TEXT).format(value)
: null;
}
@@ -99,6 +99,20 @@ protected void configureDecimalFormat(
if(feature==null)
return;
+ // lookup meta-model for any facets that provide the MaximumIntegerDigits;
+ // applies only to input (we don't want to remove most significant digits when rendering)
+ // @see ValueSemantics#maxIntegerDigits
+ if(usedFor.isParsing()) {
+ Facets.maxIntegerDigits(feature)
+ .ifPresent(format::setMaximumIntegerDigits);
+ }
+
+ // lookup meta-model for any facets that provide the MinimumIntegerDigits;
+ // applies to display and input prompting alike,
+ // @see ValueSemantics#minIntegerDigits
+ Facets.minIntegerDigits(feature)
+ .ifPresent(format::setMinimumIntegerDigits);
+
if(isFloatingPoint()) {
// lookup meta-model for any facets that provide the MaximumFractionDigits;
// applies to display and input alike
@@ -113,15 +127,6 @@ protected void configureDecimalFormat(
Facets.minFractionalDigits(feature)
.ifPresent(format::setMinimumFractionDigits);
}
-
- switch (usedFor) {
- case RENDERING_AS_TEXT, RENDERING_AS_HTML -> {
-
- }
- case PARSING -> {
-
- }
- }
}
protected Optional<BigInteger> parseInteger(
@@ -151,14 +156,26 @@ protected Optional<BigDecimal> parseDecimal(
try {
var number = formatEx.parse(input);
+ int integerDigitCount = integerDigitCount(number);
+ int fractionDigitCount = fractionDigitCount(number);
- // check for maxFractionDigits if required ...
- final int maxFractionDigits = formatEx.format().getMaximumFractionDigits();
- if(maxFractionDigits>-1
- && number.scale()>formatEx.format().getMaximumFractionDigits())
+ // check for maxIntegerDigits
+ if(integerDigitCount > formatEx.maxIntegerDigits())
+ throw new TextEntryParseException(String.format(
+ "No more than %d integer digits (digits before the decimal separator) can be entered, "
+ + "got %d in '%s'.", formatEx.maxIntegerDigits(), integerDigitCount, input));
+
+ // check for minIntegerDigits
+ if(integerDigitCount < formatEx.minIntegerDigits())
+ throw new TextEntryParseException(String.format(
+ "A minimum of %d integer digits (digits before the decimal separator) must be entered, "
+ + "got %d in '%s'.", formatEx.minIntegerDigits(), integerDigitCount, input));
+
+ // check for maxFractionDigits
+ if(fractionDigitCount>formatEx.maxFractionDigits())
throw new TextEntryParseException(String.format(
"No more than %d digits can be entered after the decimal separator, "
- + "got %d in '%s'.", maxFractionDigits, number.scale(), input));
+ + "got %d in '%s'.", formatEx.maxFractionDigits(), fractionDigitCount, input));
return Optional.of(number);
} catch (final NumberFormatException | ParseException e) {
throw new TextEntryParseException(String.format(
@@ -167,6 +184,16 @@ protected Optional<BigDecimal> parseDecimal(
}
}
+ static int fractionDigitCount(final BigDecimal number) {
+ return number.scale()>=0
+ ? number.scale()
+ : 0;
+ }
+
+ static int integerDigitCount(final BigDecimal number) {
+ return number.toBigInteger().abs().toString().length();
+ }
+
/**
* Conditionally disallows the user- or system-locale specific grouping (thousands) separator
* (being part of the input string) or at least validates, that the grouping is correctly placed.
@@ -278,6 +305,10 @@ else if (position.getIndex() < input.length())
throw new ParseException("input='" + rawInput + "' was not processed completely", position.getIndex());
return decimal;
}
+ public int maxIntegerDigits() { return format.getMaximumIntegerDigits(); }
+ public int minIntegerDigits() { return format.getMinimumIntegerDigits(); }
+ public int maxFractionDigits() { return format.getMaximumFractionDigits(); }
+ public int minFractionDigits() { return format.getMinimumFractionDigits(); }
}
/**