From 3d235bb812bd079e760b206849afcc1b6139bb3d Mon Sep 17 00:00:00 2001 From: Jeremie Bresson Date: Tue, 9 Jul 2019 20:15:33 +0200 Subject: [PATCH 1/3] [java] Support for number enum --- .../codegen/languages/AbstractJavaCodegen.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java index 066f424bfa16..8a51194cc764 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java @@ -417,6 +417,7 @@ public void processOpts() { // imports for pojos importMapping.put("ApiModelProperty", "io.swagger.annotations.ApiModelProperty"); importMapping.put("ApiModel", "io.swagger.annotations.ApiModel"); + importMapping.put("BigDecimal", "java.math.BigDecimal"); importMapping.put("JsonProperty", "com.fasterxml.jackson.annotation.JsonProperty"); importMapping.put("JsonSubTypes", "com.fasterxml.jackson.annotation.JsonSubTypes"); importMapping.put("JsonTypeInfo", "com.fasterxml.jackson.annotation.JsonTypeInfo"); @@ -944,6 +945,9 @@ public CodegenModel fromModel(String name, Schema model) { final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel); codegenModel = AbstractJavaCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel); } + if ("BigDecimal".equals(codegenModel.dataType)) { + codegenModel.imports.add("BigDecimal"); + } return codegenModel; } @@ -1107,7 +1111,7 @@ public String toEnumVarName(String value, String datatype) { // number if ("Integer".equals(datatype) || "Long".equals(datatype) || - "Float".equals(datatype) || "Double".equals(datatype)) { + "Float".equals(datatype) || "Double".equals(datatype) || "BigDecimal".equals(datatype)) { String varName = "NUMBER_" + value; varName = varName.replaceAll("-", "MINUS_"); varName = varName.replaceAll("\\+", "PLUS_"); @@ -1134,6 +1138,9 @@ public String toEnumValue(String value, String datatype) { } else if ("Float".equals(datatype)) { // add f to number, e.g. 3.14 => 3.14f return value + "f"; + } else if ("BigDecimal".equals(datatype)) { + // use BigDecimal String constructor + return "new BigDecimal(\"" + value + "\")"; } else { return "\"" + escapeText(value) + "\""; } From 572590ecb63fd359dc0155d03b75461638b3eeac Mon Sep 17 00:00:00 2001 From: Jeremie Bresson Date: Tue, 9 Jul 2019 20:16:40 +0200 Subject: [PATCH 2/3] [core] add isLong, isNumber, isNumeric, isFloat, isDouble to CodegenModel --- .../openapitools/codegen/CodegenModel.java | 7 +- .../openapitools/codegen/DefaultCodegen.java | 21 ++- .../codegen/DefaultCodegenTest.java | 160 ++++++++++++++++++ 3 files changed, 183 insertions(+), 5 deletions(-) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenModel.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenModel.java index 760033ec35de..b9e93fbf26af 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenModel.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/CodegenModel.java @@ -46,7 +46,7 @@ public class CodegenModel { public String defaultValue; public String arrayModelType; public boolean isAlias; // Is this effectively an alias of another simple type - public boolean isString, isInteger; + public boolean isString, isInteger, isLong, isNumber, isNumeric, isFloat, isDouble; public List vars = new ArrayList(); // all properties (without parent's properties) public List allVars = new ArrayList(); // all properties (with parent's properties) public List requiredVars = new ArrayList(); // a list of required properties @@ -96,7 +96,12 @@ public String toString() { .append("arrayModelType", arrayModelType) .append("isAlias", isAlias) .append("isString", isString) + .append("isNumeric", isNumeric) .append("isInteger", isInteger) + .append("isLong", isLong) + .append("isNumber", isNumber) + .append("isFloat", isFloat) + .append("isDouble", isDouble) .append("vars", vars) .append("requiredVars", requiredVars) .append("optionalVars", optionalVars) diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 5373b99e934d..5a8febbc3c79 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -1832,14 +1832,27 @@ public CodegenModel fromModel(String name, Schema schema) { addAdditionPropertiesToCodeGenModel(m, schema); m.isMapModel = true; } - if (ModelUtils.isIntegerSchema(schema)) { // integer type - if (!ModelUtils.isLongSchema(schema)) { // long type is not integer + else if (ModelUtils.isIntegerSchema(schema)) { // integer type + m.isNumeric = Boolean.TRUE; + if (ModelUtils.isLongSchema(schema)) { // int64/long format + m.isLong = Boolean.TRUE; + } else { // int32 format m.isInteger = Boolean.TRUE; } } - if (ModelUtils.isStringSchema(schema)) { + else if (ModelUtils.isStringSchema(schema)) { m.isString = Boolean.TRUE; } + else if (ModelUtils.isNumberSchema(schema)) { + m.isNumeric = Boolean.TRUE; + if (ModelUtils.isFloatSchema(schema)) { // float + m.isFloat = Boolean.TRUE; + } else if (ModelUtils.isDoubleSchema(schema)) { // double + m.isDouble = Boolean.TRUE; + } else { // type is number and without format + m.isNumber = Boolean.TRUE; + } + } // passing null to allProperties and allRequired as there's no parent addVars(m, unaliasPropertySchema(schema.getProperties()), schema.getRequired(), null, null); @@ -2006,7 +2019,7 @@ public CodegenProperty fromProperty(String name, Schema p) { String type = getSchemaType(p); if (ModelUtils.isIntegerSchema(p)) { // integer type property.isNumeric = Boolean.TRUE; - if (SchemaTypeUtil.INTEGER64_FORMAT.equals(p.getFormat())) { // int64/long format + if (ModelUtils.isLongSchema(p)) { // int64/long format property.isLong = Boolean.TRUE; } else { // int32 format property.isInteger = Boolean.TRUE; diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java index a95b6f106b1c..871958108e85 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/DefaultCodegenTest.java @@ -578,6 +578,166 @@ public void testNullableProperty() { Assert.assertTrue(property.isNullable); } + @Test + public void integerSchemaPropertyAndModelTest() { + OpenAPI openAPI = TestUtils.createOpenAPI(); + final Schema schema = new IntegerSchema().format("int32"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + //Property: + final CodegenProperty cp = codegen.fromProperty("someProperty", schema); + Assert.assertEquals(cp.baseType, "integer"); + Assert.assertEquals(cp.baseName, "someProperty"); + Assert.assertFalse(cp.isString); + Assert.assertTrue(cp.isInteger); + Assert.assertFalse(cp.isLong); + Assert.assertFalse(cp.isNumber); + Assert.assertTrue(cp.isNumeric); + Assert.assertFalse(cp.isFloat); + Assert.assertFalse(cp.isDouble); + + //Model: + final CodegenModel cm = codegen.fromModel("someModel", schema); + Assert.assertEquals(cm.dataType, "integer"); + Assert.assertEquals(cm.name, "someModel"); + Assert.assertFalse(cm.isString); + Assert.assertTrue(cm.isInteger); + Assert.assertFalse(cm.isLong); + Assert.assertFalse(cm.isNumber); + Assert.assertTrue(cm.isNumeric); + Assert.assertFalse(cm.isFloat); + Assert.assertFalse(cm.isDouble); + } + + @Test + public void longSchemaPropertyAndModelTest() { + OpenAPI openAPI = TestUtils.createOpenAPI(); + final Schema schema = new IntegerSchema().format("int64"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + //Property: + final CodegenProperty cp = codegen.fromProperty("someProperty", schema); + Assert.assertEquals(cp.baseType, "long"); + Assert.assertEquals(cp.baseName, "someProperty"); + Assert.assertFalse(cp.isString); + Assert.assertFalse(cp.isInteger); + Assert.assertTrue(cp.isLong); + Assert.assertFalse(cp.isNumber); + Assert.assertTrue(cp.isNumeric); + Assert.assertFalse(cp.isFloat); + Assert.assertFalse(cp.isDouble); + + //Model: + final CodegenModel cm = codegen.fromModel("someModel", schema); + Assert.assertEquals(cm.dataType, "long"); + Assert.assertEquals(cm.name, "someModel"); + Assert.assertFalse(cm.isString); + Assert.assertFalse(cm.isInteger); + Assert.assertTrue(cm.isLong); + Assert.assertFalse(cm.isNumber); + Assert.assertTrue(cm.isNumeric); + Assert.assertFalse(cm.isFloat); + Assert.assertFalse(cm.isDouble); + } + + @Test + public void numberSchemaPropertyAndModelTest() { + OpenAPI openAPI = TestUtils.createOpenAPI(); + final Schema schema = new NumberSchema(); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + //Property: + final CodegenProperty cp = codegen.fromProperty("someProperty", schema); + Assert.assertEquals(cp.baseType, "number"); + Assert.assertEquals(cp.baseName, "someProperty"); + Assert.assertFalse(cp.isString); + Assert.assertFalse(cp.isInteger); + Assert.assertFalse(cp.isLong); + Assert.assertTrue(cp.isNumber); + Assert.assertTrue(cp.isNumeric); + Assert.assertFalse(cp.isFloat); + Assert.assertFalse(cp.isDouble); + + //Model: + final CodegenModel cm = codegen.fromModel("someModel", schema); + Assert.assertEquals(cm.dataType, "number"); + Assert.assertEquals(cm.name, "someModel"); + Assert.assertFalse(cm.isString); + Assert.assertFalse(cm.isInteger); + Assert.assertFalse(cm.isLong); + Assert.assertTrue(cm.isNumber); + Assert.assertTrue(cm.isNumeric); + Assert.assertFalse(cm.isFloat); + Assert.assertFalse(cm.isDouble); + } + + @Test + public void numberFloatSchemaPropertyAndModelTest() { + OpenAPI openAPI = TestUtils.createOpenAPI(); + final Schema schema = new NumberSchema().format("float"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + //Property: + final CodegenProperty cp = codegen.fromProperty("someProperty", schema); + Assert.assertEquals(cp.baseType, "float"); + Assert.assertEquals(cp.baseName, "someProperty"); + Assert.assertFalse(cp.isString); + Assert.assertFalse(cp.isInteger); + Assert.assertFalse(cp.isLong); + Assert.assertFalse(cp.isNumber); + Assert.assertTrue(cp.isNumeric); + Assert.assertTrue(cp.isFloat); + Assert.assertFalse(cp.isDouble); + + //Model: + final CodegenModel cm = codegen.fromModel("someModel", schema); + Assert.assertEquals(cm.dataType, "float"); + Assert.assertEquals(cm.name, "someModel"); + Assert.assertFalse(cm.isString); + Assert.assertFalse(cm.isInteger); + Assert.assertFalse(cm.isLong); + Assert.assertFalse(cm.isNumber); + Assert.assertTrue(cm.isNumeric); + Assert.assertTrue(cm.isFloat); + Assert.assertFalse(cm.isDouble); + } + + @Test + public void numberDoubleSchemaPropertyAndModelTest() { + OpenAPI openAPI = TestUtils.createOpenAPI(); + final Schema schema = new NumberSchema().format("double"); + final DefaultCodegen codegen = new DefaultCodegen(); + codegen.setOpenAPI(openAPI); + + //Property: + final CodegenProperty cp = codegen.fromProperty("someProperty", schema); + Assert.assertEquals(cp.baseType, "double"); + Assert.assertEquals(cp.baseName, "someProperty"); + Assert.assertFalse(cp.isString); + Assert.assertFalse(cp.isInteger); + Assert.assertFalse(cp.isLong); + Assert.assertFalse(cp.isNumber); + Assert.assertTrue(cp.isNumeric); + Assert.assertFalse(cp.isFloat); + Assert.assertTrue(cp.isDouble); + + //Model: + final CodegenModel cm = codegen.fromModel("someModel", schema); + Assert.assertEquals(cm.dataType, "double"); + Assert.assertEquals(cm.name, "someModel"); + Assert.assertFalse(cm.isString); + Assert.assertFalse(cm.isInteger); + Assert.assertFalse(cm.isLong); + Assert.assertFalse(cm.isNumber); + Assert.assertTrue(cm.isNumeric); + Assert.assertFalse(cm.isFloat); + Assert.assertTrue(cm.isDouble); + } + private void verifyPersonDiscriminator(CodegenDiscriminator discriminator) { CodegenDiscriminator test = new CodegenDiscriminator(); test.setPropertyName("DollarUnderscoretype"); From 2a1d4db5f0795dde8c73cddc865ade680b15e16b Mon Sep 17 00:00:00 2001 From: Jeremie Bresson Date: Tue, 9 Jul 2019 07:41:52 +0200 Subject: [PATCH 3/3] [java-gson] fix Enum TypeAdapter in BigDecimal case. --- .../src/main/resources/Java/modelEnum.mustache | 4 ++-- .../src/main/resources/Java/modelInnerEnum.mustache | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/Java/modelEnum.mustache b/modules/openapi-generator/src/main/resources/Java/modelEnum.mustache index e22a8e6ecee6..f9136b1a2011 100644 --- a/modules/openapi-generator/src/main/resources/Java/modelEnum.mustache +++ b/modules/openapi-generator/src/main/resources/Java/modelEnum.mustache @@ -65,8 +65,8 @@ public enum {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum @Override public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { - {{{dataType}}} value = jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}; - return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue(value); + {{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}{{/isNumber}}; + return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{{classname}}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}}); } } {{/gson}} diff --git a/modules/openapi-generator/src/main/resources/Java/modelInnerEnum.mustache b/modules/openapi-generator/src/main/resources/Java/modelInnerEnum.mustache index 87c23108c11a..ea0656c2ddf6 100644 --- a/modules/openapi-generator/src/main/resources/Java/modelInnerEnum.mustache +++ b/modules/openapi-generator/src/main/resources/Java/modelInnerEnum.mustache @@ -56,8 +56,8 @@ @Override public {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}} read(final JsonReader jsonReader) throws IOException { - {{{dataType}}} value = jsonReader.{{#isInteger}}nextInt(){{/isInteger}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}; - return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue(value); + {{^isNumber}}{{{dataType}}}{{/isNumber}}{{#isNumber}}String{{/isNumber}} value = jsonReader.{{#isNumber}}nextString(){{/isNumber}}{{#isInteger}}nextInt(){{/isInteger}}{{^isNumber}}{{^isInteger}}next{{{dataType}}}(){{/isInteger}}{{/isNumber}}; + return {{#datatypeWithEnum}}{{{.}}}{{/datatypeWithEnum}}{{^datatypeWithEnum}}{{classname}}{{/datatypeWithEnum}}.fromValue({{#isNumber}}new BigDecimal({{/isNumber}}value{{#isNumber}}){{/isNumber}}); } } {{/gson}}