-
-
Notifications
You must be signed in to change notification settings - Fork 7.7k
[Java] generation for unsinged integers #24764
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
4b5939c
84b4859
ebb6ca8
95030c0
d1060a7
518fd72
aef5fc5
6d446b1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -61,6 +61,8 @@ | |||||||||||||||||||||||||||||||||
| import java.io.File; | ||||||||||||||||||||||||||||||||||
| import java.io.IOException; | ||||||||||||||||||||||||||||||||||
| import java.io.Writer; | ||||||||||||||||||||||||||||||||||
| import java.math.BigDecimal; | ||||||||||||||||||||||||||||||||||
| import java.math.BigInteger; | ||||||||||||||||||||||||||||||||||
| import java.time.LocalDate; | ||||||||||||||||||||||||||||||||||
| import java.time.ZoneId; | ||||||||||||||||||||||||||||||||||
| import java.time.ZonedDateTime; | ||||||||||||||||||||||||||||||||||
|
|
@@ -87,6 +89,10 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code | |||||||||||||||||||||||||||||||||
| private final Logger LOGGER = LoggerFactory.getLogger(AbstractJavaCodegen.class); | ||||||||||||||||||||||||||||||||||
| private static final String ARTIFACT_VERSION_DEFAULT_VALUE = "1.0.0"; | ||||||||||||||||||||||||||||||||||
| private static final ZoneId UTC = ZoneId.of("UTC"); | ||||||||||||||||||||||||||||||||||
| private static final BigInteger INTEGER_MIN_VALUE = BigInteger.valueOf(Integer.MIN_VALUE); | ||||||||||||||||||||||||||||||||||
| private static final BigInteger INTEGER_MAX_VALUE = BigInteger.valueOf(Integer.MAX_VALUE); | ||||||||||||||||||||||||||||||||||
| private static final BigInteger LONG_MIN_VALUE = BigInteger.valueOf(Long.MIN_VALUE); | ||||||||||||||||||||||||||||||||||
| private static final BigInteger LONG_MAX_VALUE = BigInteger.valueOf(Long.MAX_VALUE); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| public static final String DEFAULT_LIBRARY = "<default>"; | ||||||||||||||||||||||||||||||||||
| public static final String DATE_LIBRARY = "dateLibrary"; | ||||||||||||||||||||||||||||||||||
|
|
@@ -304,8 +310,10 @@ public AbstractJavaCodegen() { | |||||||||||||||||||||||||||||||||
| typeMapping.put("date", "Date"); | ||||||||||||||||||||||||||||||||||
| typeMapping.put("file", "File"); | ||||||||||||||||||||||||||||||||||
| typeMapping.put("AnyType", "Object"); | ||||||||||||||||||||||||||||||||||
| typeMapping.put("BigInteger", "BigInteger"); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| importMapping.put("BigDecimal", "java.math.BigDecimal"); | ||||||||||||||||||||||||||||||||||
| importMapping.put("BigInteger", "java.math.BigInteger"); | ||||||||||||||||||||||||||||||||||
| importMapping.put("UUID", "java.util.UUID"); | ||||||||||||||||||||||||||||||||||
| importMapping.put("URI", "java.net.URI"); | ||||||||||||||||||||||||||||||||||
| importMapping.put("File", "java.io.File"); | ||||||||||||||||||||||||||||||||||
|
|
@@ -1909,6 +1917,21 @@ public String toExampleValue(Schema p) { | |||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||
| public String getSchemaType(Schema p) { | ||||||||||||||||||||||||||||||||||
| if (ModelUtils.isIntegerSchema(p)) { | ||||||||||||||||||||||||||||||||||
| // legacy, non-standard `uint32`/`uint64` integer formats: since Java has no native | ||||||||||||||||||||||||||||||||||
| // unsigned integer types, widen them to a type that can hold the full unsigned range | ||||||||||||||||||||||||||||||||||
| if ("uint32".equals(p.getFormat())) { | ||||||||||||||||||||||||||||||||||
| return typeMapping.get("long"); | ||||||||||||||||||||||||||||||||||
| } else if ("uint64".equals(p.getFormat())) { | ||||||||||||||||||||||||||||||||||
|
tisis2 marked this conversation as resolved.
|
||||||||||||||||||||||||||||||||||
| return typeMapping.get("BigInteger"); | ||||||||||||||||||||||||||||||||||
| } else if (StringUtils.isEmpty(p.getFormat()) && hasIntegerBounds(p)) { | ||||||||||||||||||||||||||||||||||
| // no format given: infer the smallest type (Integer/Long/BigInteger) that fits minimum/maximum, | ||||||||||||||||||||||||||||||||||
| // the same way the rust-axum generator picks its integer types | ||||||||||||||||||||||||||||||||||
| return bestFittingIntegerType(integerBound(p.getMinimum()), Boolean.TRUE.equals(p.getExclusiveMinimum()), | ||||||||||||||||||||||||||||||||||
| integerBound(p.getMaximum()), Boolean.TRUE.equals(p.getExclusiveMaximum())); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| String openAPIType = super.getSchemaType(p); | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| // don't apply renaming on types from the typeMapping | ||||||||||||||||||||||||||||||||||
|
|
@@ -1922,6 +1945,74 @@ public String getSchemaType(Schema p) { | |||||||||||||||||||||||||||||||||
| return toModelName(openAPIType); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| private boolean hasIntegerBounds(Schema p) { | ||||||||||||||||||||||||||||||||||
| return p.getMinimum() != null || p.getMaximum() != null; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| private BigInteger integerBound(BigDecimal bound) { | ||||||||||||||||||||||||||||||||||
| return bound == null ? null : bound.toBigInteger(); | ||||||||||||||||||||||||||||||||||
|
tisis2 marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||||
| * Determine the smallest Java integer type (Integer, Long or BigInteger) that can represent every | ||||||||||||||||||||||||||||||||||
| * value in the given [minimum, maximum] range. Missing bounds are treated as unbounded on that side. | ||||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||||
| private String bestFittingIntegerType(BigInteger minimum, boolean exclusiveMinimum, | ||||||||||||||||||||||||||||||||||
| BigInteger maximum, boolean exclusiveMaximum) { | ||||||||||||||||||||||||||||||||||
| if (exclusiveMinimum && minimum != null) { | ||||||||||||||||||||||||||||||||||
| minimum = minimum.add(BigInteger.ONE); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| if (exclusiveMaximum && maximum != null) { | ||||||||||||||||||||||||||||||||||
| maximum = maximum.subtract(BigInteger.ONE); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if ((minimum == null || minimum.compareTo(INTEGER_MIN_VALUE) >= 0) | ||||||||||||||||||||||||||||||||||
| && (maximum == null || maximum.compareTo(INTEGER_MAX_VALUE) <= 0)) { | ||||||||||||||||||||||||||||||||||
| return typeMapping.get("integer"); | ||||||||||||||||||||||||||||||||||
| } else if ((minimum == null || minimum.compareTo(LONG_MIN_VALUE) >= 0) | ||||||||||||||||||||||||||||||||||
| && (maximum == null || maximum.compareTo(LONG_MAX_VALUE) <= 0)) { | ||||||||||||||||||||||||||||||||||
| return typeMapping.get("long"); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| return typeMapping.get("BigInteger"); | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+1981
to
+1988
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: For a one-sided integer range, the missing side is unbounded, so Prompt for AI agents
Suggested change
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. wouldn't that mean that every integer without a range that was previously generated as Integer, now would be generated as BigInteger and breaking the generated API usage? |
||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
tisis2 marked this conversation as resolved.
Outdated
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||
| protected void updatePropertyForInteger(CodegenProperty property, Schema p) { | ||||||||||||||||||||||||||||||||||
| // legacy, non-standard `uint32`/`uint64` integer formats (see getSchemaType above) | ||||||||||||||||||||||||||||||||||
| if ("uint32".equals(p.getFormat())) { | ||||||||||||||||||||||||||||||||||
| property.isNumeric = Boolean.TRUE; | ||||||||||||||||||||||||||||||||||
| property.isLong = Boolean.TRUE; | ||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||
| } else if ("uint64".equals(p.getFormat())) { | ||||||||||||||||||||||||||||||||||
| property.isNumeric = Boolean.TRUE; | ||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||
| } else if (StringUtils.isEmpty(p.getFormat()) && hasIntegerBounds(p)) { | ||||||||||||||||||||||||||||||||||
| property.isNumeric = Boolean.TRUE; | ||||||||||||||||||||||||||||||||||
| String inferredType = bestFittingIntegerType(integerBound(p.getMinimum()), Boolean.TRUE.equals(p.getExclusiveMinimum()), | ||||||||||||||||||||||||||||||||||
| integerBound(p.getMaximum()), Boolean.TRUE.equals(p.getExclusiveMaximum())); | ||||||||||||||||||||||||||||||||||
| if (typeMapping.get("long").equals(inferredType)) { | ||||||||||||||||||||||||||||||||||
| property.isLong = Boolean.TRUE; | ||||||||||||||||||||||||||||||||||
| } else if (!typeMapping.get("BigInteger").equals(inferredType)) { | ||||||||||||||||||||||||||||||||||
| property.isInteger = Boolean.TRUE; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| super.updatePropertyForInteger(property, p); | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||
| public void postProcessParameter(CodegenParameter parameter) { | ||||||||||||||||||||||||||||||||||
| // keep isLong/isInteger in sync with the widened dataType from uint32/uint64 formats and | ||||||||||||||||||||||||||||||||||
| // range-inferred Long/BigInteger types (see getSchemaType/updatePropertyForInteger above) | ||||||||||||||||||||||||||||||||||
| if (typeMapping.get("long").equals(parameter.dataType)) { | ||||||||||||||||||||||||||||||||||
| parameter.isInteger = false; | ||||||||||||||||||||||||||||||||||
| parameter.isLong = true; | ||||||||||||||||||||||||||||||||||
| } else if (typeMapping.get("BigInteger").equals(parameter.dataType)) { | ||||||||||||||||||||||||||||||||||
| parameter.isInteger = false; | ||||||||||||||||||||||||||||||||||
| parameter.isLong = false; | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @Override | ||||||||||||||||||||||||||||||||||
| public String toOperationId(String operationId) { | ||||||||||||||||||||||||||||||||||
| // throw exception if method name is empty | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.