diff --git a/docs/generators/dart-dio.md b/docs/generators/dart-dio.md index 0841a791b9d4..8a4e575ab85b 100644 --- a/docs/generators/dart-dio.md +++ b/docs/generators/dart-dio.md @@ -17,3 +17,4 @@ sidebar_label: dart-dio |sourceFolder|Source folder for generated code| |null| |supportDart2|Support Dart 2.x (Dart 1.x support has been deprecated)| |true| |nullableFields|Is the null fields should be in the JSON payload| |null| +|dateLibrary|Option. Date library to use|
**core**
Dart core library (DateTime)
**timemachine**
Time Machine is date and time library for Flutter, Web, and Server with support for timezones, calendars, cultures, formatting and parsing.
|core| diff --git a/modules/openapi-generator/pom.xml b/modules/openapi-generator/pom.xml index 316d2a65e077..d7f47c741416 100644 --- a/modules/openapi-generator/pom.xml +++ b/modules/openapi-generator/pom.xml @@ -243,6 +243,11 @@ slf4j-api ${slf4j-version} + + org.slf4j + slf4j-simple + ${slf4j-version} + org.apache.commons commons-lang3 diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java index 0729817c4891..34404fd1efdb 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/DartDioClientCodegen.java @@ -16,6 +16,7 @@ package org.openapitools.codegen.languages; +import java.util.HashMap; import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.CliOption; import org.openapitools.codegen.CodegenConstants; @@ -44,9 +45,10 @@ public class DartDioClientCodegen extends DartClientCodegen { private static final Logger LOGGER = LoggerFactory.getLogger(DartDioClientCodegen.class); - private static final String NULLABLE_FIELDS = "nullableFields"; + public static final String NULLABLE_FIELDS = "nullableFields"; private static final String IS_FORMAT_JSON = "jsonFormat"; private static final String CLIENT_NAME = "clientName"; + public static final String DATE_LIBRARY = "dateLibrary"; private static Set modelToIgnore = new HashSet<>(); @@ -62,6 +64,7 @@ public class DartDioClientCodegen extends DartClientCodegen { private static final String SERIALIZATION_JSON = "json"; private boolean nullableFields = true; + private String dateLibrary = "core"; public DartDioClientCodegen() { super(); @@ -74,6 +77,12 @@ public DartDioClientCodegen() { apiTestTemplateFiles.clear(); cliOptions.add(new CliOption(NULLABLE_FIELDS, "Is the null fields should be in the JSON payload")); + CliOption dateLibrary = new CliOption(DATE_LIBRARY, "Option. Date library to use").defaultValue(this.getDateLibrary()); + Map dateOptions = new HashMap<>(); + dateOptions.put("core", "Dart core library (DateTime)"); + dateOptions.put("timemachine", "Time Machine is date and time library for Flutter, Web, and Server with support for timezones, calendars, cultures, formatting and parsing."); + dateLibrary.setEnum(dateOptions); + cliOptions.add(dateLibrary); typeMapping.put("file", "Uint8List"); typeMapping.put("binary", "Uint8List"); @@ -84,6 +93,23 @@ public DartDioClientCodegen() { importMapping.put("Uint8List", "dart:typed_data"); } + public String getDateLibrary() { + return dateLibrary; + } + + public void setDateLibrary(String library) { + this.dateLibrary = library; + } + + public boolean getNullableFields() { + return nullableFields; + } + + public void setNullableFields(boolean nullableFields) { + this.nullableFields = nullableFields; + } + + @Override public String getName() { return "dart-dio"; @@ -94,6 +120,10 @@ public String getHelp() { return "Generates a Dart Dio client library."; } + @Override public void setBrowserClient(boolean browserClient) { + super.browserClient = browserClient; + } + @Override public String toDefaultValue(Schema p) { if (ModelUtils.isMapSchema(p)) { @@ -105,11 +135,10 @@ public String toDefaultValue(Schema p) { } @Override - public String escapeReservedWord(String name) { - if (this.reservedWordsMappings().containsKey(name)) { - return this.reservedWordsMappings().get(name); - } - return "_" + name; + protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) { + //super.addAdditionPropertiesToCodeGenModel(codegenModel, schema); + codegenModel.additionalPropertiesType = getSchemaType(ModelUtils.getAdditionalProperties(schema)); + addImport(codegenModel, codegenModel.additionalPropertiesType); } @Override @@ -117,12 +146,10 @@ public String toEnumVarName(String name, String datatype) { if (name.length() == 0) { return "empty"; } - if ("number".equalsIgnoreCase(datatype) || - "int".equalsIgnoreCase(datatype)) { + if ("number".equalsIgnoreCase(datatype) || "int".equalsIgnoreCase(datatype)) { name = "Number" + name; } name = camelize(name, true); - // for reserved word or word starting with number, append _ if (isReservedWord(name) || name.matches("^\\d.*")) { name = escapeReservedWord(name); @@ -130,22 +157,92 @@ public String toEnumVarName(String name, String datatype) { return name; } - @Override - protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Schema schema) { - //super.addAdditionPropertiesToCodeGenModel(codegenModel, schema); - codegenModel.additionalPropertiesType = getSchemaType(ModelUtils.getAdditionalProperties(schema)); - addImport(codegenModel, codegenModel.additionalPropertiesType); - } - @Override public void processOpts() { + if (additionalProperties.containsKey(CodegenConstants.TEMPLATE_DIR)) { + this.setTemplateDir((String) additionalProperties.get(CodegenConstants.TEMPLATE_DIR)); + } + + if (additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) { + this.setModelPackage((String) additionalProperties.get(CodegenConstants.MODEL_PACKAGE)); + } + + if (additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) { + this.setApiPackage((String) additionalProperties.get(CodegenConstants.API_PACKAGE)); + } + + if (additionalProperties.containsKey(CodegenConstants.HIDE_GENERATION_TIMESTAMP)) { + setHideGenerationTimestamp(convertPropertyToBooleanAndWriteBack(CodegenConstants.HIDE_GENERATION_TIMESTAMP)); + } else { + additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, hideGenerationTimestamp); + } + + if (additionalProperties.containsKey(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG)) { + this.setSortParamsByRequiredFlag(Boolean.valueOf(additionalProperties + .get(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG).toString())); + } + + if (additionalProperties.containsKey(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS)) { + this.setPrependFormOrBodyParameters(Boolean.valueOf(additionalProperties + .get(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS).toString())); + } + + if (additionalProperties.containsKey(CodegenConstants.ENSURE_UNIQUE_PARAMS)) { + this.setEnsureUniqueParams(Boolean.valueOf(additionalProperties + .get(CodegenConstants.ENSURE_UNIQUE_PARAMS).toString())); + } + + if (additionalProperties.containsKey(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS)) { + this.setAllowUnicodeIdentifiers(Boolean.valueOf(additionalProperties + .get(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS).toString())); + } + + if (additionalProperties.containsKey(CodegenConstants.API_NAME_SUFFIX)) { + this.setApiNameSuffix((String) additionalProperties.get(CodegenConstants.API_NAME_SUFFIX)); + } + + if (additionalProperties.containsKey(CodegenConstants.MODEL_NAME_PREFIX)) { + this.setModelNamePrefix((String) additionalProperties.get(CodegenConstants.MODEL_NAME_PREFIX)); + } + + if (additionalProperties.containsKey(CodegenConstants.MODEL_NAME_SUFFIX)) { + this.setModelNameSuffix((String) additionalProperties.get(CodegenConstants.MODEL_NAME_SUFFIX)); + } + + if (additionalProperties.containsKey(CodegenConstants.REMOVE_OPERATION_ID_PREFIX)) { + this.setRemoveOperationIdPrefix(Boolean.valueOf(additionalProperties + .get(CodegenConstants.REMOVE_OPERATION_ID_PREFIX).toString())); + } + + if (additionalProperties.containsKey(CodegenConstants.DOCEXTENSION)) { + this.setDocExtension(String.valueOf(additionalProperties + .get(CodegenConstants.DOCEXTENSION).toString())); + } + + if (additionalProperties.containsKey(CodegenConstants.ENABLE_POST_PROCESS_FILE)) { + this.setEnablePostProcessFile(Boolean.valueOf(additionalProperties + .get(CodegenConstants.ENABLE_POST_PROCESS_FILE).toString())); + } + + if (additionalProperties.containsKey(CodegenConstants.GENERATE_ALIAS_AS_MODEL)) { + ModelUtils.setGenerateAliasAsModel(Boolean.valueOf(additionalProperties + .get(CodegenConstants.GENERATE_ALIAS_AS_MODEL).toString())); + } + if (StringUtils.isEmpty(System.getenv("DART_POST_PROCESS_FILE"))) { LOGGER.info("Environment variable DART_POST_PROCESS_FILE not defined so the Dart code may not be properly formatted. To define it, try `export DART_POST_PROCESS_FILE=\"/usr/local/bin/dartfmt -w\"` (Linux/Mac)"); LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI)."); } + if (additionalProperties.containsKey(BROWSER_CLIENT)) { + this.setBrowserClient(convertPropertyToBooleanAndWriteBack(BROWSER_CLIENT)); + } else { + //not set, use to be passed to template + additionalProperties.put(BROWSER_CLIENT, browserClient); + } + if (additionalProperties.containsKey(NULLABLE_FIELDS)) { - nullableFields = convertPropertyToBooleanAndWriteBack(NULLABLE_FIELDS); + this.setNullableFields(convertPropertyToBooleanAndWriteBack(NULLABLE_FIELDS)); } else { //not set, use to be passed to template additionalProperties.put(NULLABLE_FIELDS, nullableFields); @@ -189,6 +286,9 @@ public void processOpts() { this.setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER)); } + if (additionalProperties.containsKey(DATE_LIBRARY)) { + this.setDateLibrary(additionalProperties.get(DATE_LIBRARY).toString()); + } // make api and model doc path available in mustache template additionalProperties.put("apiDocPath", apiDocPath); additionalProperties.put("modelDocPath", modelDocPath); @@ -201,6 +301,24 @@ public void processOpts() { supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore")); supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); + + if ("core".equals(dateLibrary)) { + additionalProperties.put("core", "true"); + typeMapping.put("Date", "DateTime"); + typeMapping.put("date", "DateTime"); + importMapping.put("DateTime", "DateTime"); + importMapping.put("OffsetDateTime", "DateTime"); + } else if ("timemachine".equals(dateLibrary)) { + additionalProperties.put("timeMachine", "true"); + typeMapping.put("date", "LocalDate"); + typeMapping.put("Date", "LocalDate"); + typeMapping.put("DateTime", "OffsetDateTime"); + typeMapping.put("datetime", "OffsetDateTime"); + importMapping.put("LocalDate", "package:time_machine/time_machine.dart"); + importMapping.put("OffsetDateTime", "package:time_machine/time_machine.dart"); + supportingFiles.add(new SupportingFile("local_date_serializer.mustache", libFolder, "local_date_serializer.dart")); + + } } @Override @@ -321,4 +439,6 @@ public Map postProcessOperationsWithModels(Map o return objs; } + + } diff --git a/modules/openapi-generator/src/main/resources/dart-dio/local_date_serializer.mustache b/modules/openapi-generator/src/main/resources/dart-dio/local_date_serializer.mustache new file mode 100644 index 000000000000..2fb73ef0aae6 --- /dev/null +++ b/modules/openapi-generator/src/main/resources/dart-dio/local_date_serializer.mustache @@ -0,0 +1,23 @@ +import 'package:built_collection/built_collection.dart'; +import 'package:built_value/serializer.dart'; +import 'package:time_machine/time_machine.dart'; + +class LocalDateSerializer implements PrimitiveSerializer { + @override + Iterable get types => BuiltList([LocalDate]); + + @override + String get wireName => "LocalDate"; + + @override + LocalDate deserialize(Serializers serializers, Object serialized, + {FullType specifiedType = FullType.unspecified}) { + return LocalDate.dateTime(DateTime.parse(serialized as String)); + } + + @override + Object serialize(Serializers serializers, LocalDate localDate, + {FullType specifiedType = FullType.unspecified}) { + return localDate.toString('yyyy-MM-dd'); + } +} diff --git a/modules/openapi-generator/src/main/resources/dart-dio/pubspec.mustache b/modules/openapi-generator/src/main/resources/dart-dio/pubspec.mustache index 0cfa432854b1..90b1b532962d 100644 --- a/modules/openapi-generator/src/main/resources/dart-dio/pubspec.mustache +++ b/modules/openapi-generator/src/main/resources/dart-dio/pubspec.mustache @@ -7,7 +7,10 @@ dependencies: dio: ^3.0.4 built_value: ^6.8.2 built_collection: ^4.2.2 +{{#timeMachine}} + time_machine: ^0.9.12 +{{/timeMachine}} dev_dependencies: built_value_generator: ^6.8.2 build_runner: ^1.7.1 - test: 1.6.5 \ No newline at end of file + test: 1.6.5 diff --git a/modules/openapi-generator/src/main/resources/dart-dio/serializers.mustache b/modules/openapi-generator/src/main/resources/dart-dio/serializers.mustache index dea3a0ecff1b..2d850a28c909 100644 --- a/modules/openapi-generator/src/main/resources/dart-dio/serializers.mustache +++ b/modules/openapi-generator/src/main/resources/dart-dio/serializers.mustache @@ -4,7 +4,7 @@ import 'package:built_value/serializer.dart'; import 'package:built_collection/built_collection.dart'; import 'package:built_value/json_object.dart'; import 'package:built_value/standard_json_plugin.dart'; - +{{#timeMachine}}import 'package:{{pubName}}/local_date_serializer.dart';{{/timeMachine}} {{#models}}{{#model}}import 'package:{{pubName}}/model/{{classFilename}}.dart'; {{/model}}{{/models}} @@ -24,4 +24,5 @@ const FullType(BuiltList, const [const FullType({{classname}})]), ).build(); Serializers standardSerializers = -(serializers.toBuilder()..addPlugin(StandardJsonPlugin())).build(); +(serializers.toBuilder() +{{#timeMachine}}..add(LocalDateSerializer()){{/timeMachine}}..addPlugin(StandardJsonPlugin())).build(); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dartdio/DartDioClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dartdio/DartDioClientCodegenTest.java new file mode 100644 index 000000000000..1935a3cb95f9 --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dartdio/DartDioClientCodegenTest.java @@ -0,0 +1,86 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * Copyright 2018 SmartBear Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen.dartdio; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import org.openapitools.codegen.CodegenConstants; +import org.openapitools.codegen.languages.DartDioClientCodegen; +import org.openapitools.codegen.languages.DartDioClientCodegen; +import org.testng.Assert; +import org.testng.annotations.Test; + +public class DartDioClientCodegenTest { + + @Test + public void testInitialConfigValues() throws Exception { + final DartDioClientCodegen codegen = new DartDioClientCodegen(); + codegen.processOpts(); + + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP), Boolean.TRUE); + Assert.assertEquals(codegen.isHideGenerationTimestamp(), true); + } + + @Test + public void testSettersForConfigValues() throws Exception { + final DartDioClientCodegen codegen = new DartDioClientCodegen(); + codegen.setHideGenerationTimestamp(false); + codegen.processOpts(); + + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP), Boolean.FALSE); + Assert.assertEquals(codegen.isHideGenerationTimestamp(), false); + } + + @Test + public void testAdditionalPropertiesPutForConfigValues() throws Exception { + final DartDioClientCodegen codegen = new DartDioClientCodegen(); + codegen.additionalProperties().put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, false); + codegen.processOpts(); + + Assert.assertEquals(codegen.additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP), Boolean.FALSE); + Assert.assertEquals(codegen.isHideGenerationTimestamp(), false); + } + + @Test + public void testKeywords() throws Exception { + final DartDioClientCodegen codegen = new DartDioClientCodegen(); + + List reservedWordsList = new ArrayList(); + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream("src/main/resources/dart/dart-keywords.txt"), Charset.forName("UTF-8"))); + while(reader.ready()) { reservedWordsList.add(reader.readLine()); } + reader.close(); + } catch (Exception e) { + String errorString = String.format(Locale.ROOT, "Error reading dart keywords: %s", e); + Assert.fail(errorString, e); + } + + Assert.assertEquals(reservedWordsList.size() > 20, true); + Assert.assertEquals(codegen.reservedWords().size() == reservedWordsList.size(), true); + for(String keyword : reservedWordsList) { + // reserved words are stored in lowercase + Assert.assertEquals(codegen.reservedWords().contains(keyword.toLowerCase(Locale.ROOT)), true, String.format(Locale.ROOT, "%s, part of %s, was not found in %s", keyword, reservedWordsList, codegen.reservedWords().toString())); + } + } + +} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dartdio/DartDioClientOptionsTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dartdio/DartDioClientOptionsTest.java new file mode 100644 index 000000000000..f59c02ddf487 --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dartdio/DartDioClientOptionsTest.java @@ -0,0 +1,67 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * Copyright 2018 SmartBear Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen.dartdio; + +import mockit.Expectations; +import mockit.Tested; +import org.openapitools.codegen.AbstractOptionsTest; +import org.openapitools.codegen.CodegenConfig; +import org.openapitools.codegen.languages.DartClientCodegen; +import org.openapitools.codegen.languages.DartDioClientCodegen; +import org.openapitools.codegen.options.DartDioClientOptionsProvider; +import org.openapitools.codegen.options.DartDioClientOptionsProvider; + +public class DartDioClientOptionsTest extends AbstractOptionsTest { + + @Tested + private DartDioClientCodegen clientCodegen; + + public DartDioClientOptionsTest() { + super(new DartDioClientOptionsProvider()); + } + + @Override + protected CodegenConfig getCodegenConfig() { + return clientCodegen; + } + + @SuppressWarnings("unused") + @Override + protected void setExpectations() { + new Expectations(clientCodegen) {{ + clientCodegen.setSortParamsByRequiredFlag(Boolean.valueOf(DartDioClientOptionsProvider.SORT_PARAMS_VALUE)); + times = 1; + clientCodegen.setBrowserClient(Boolean.valueOf(DartDioClientOptionsProvider.BROWSER_CLIENT_VALUE)); + times = 1; + clientCodegen.setPubName(DartDioClientOptionsProvider.PUB_NAME_VALUE); + times = 1; + clientCodegen.setPubVersion(DartDioClientOptionsProvider.PUB_VERSION_VALUE); + times = 1; + clientCodegen.setPubDescription(DartDioClientOptionsProvider.PUB_DESCRIPTION_VALUE); + times = 1; + clientCodegen.setSourceFolder(DartDioClientOptionsProvider.SOURCE_FOLDER_VALUE); + times = 1; + clientCodegen.setUseEnumExtension(Boolean.valueOf(DartDioClientOptionsProvider.USE_ENUM_EXTENSION)); + times = 1; + clientCodegen.setDateLibrary(DartDioClientOptionsProvider.DATE_LIBRARY); + times = 1; + clientCodegen.setNullableFields(Boolean.valueOf(DartDioClientOptionsProvider.NULLABLE_FIELDS)); + times = 1; + }}; + } +} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/dartdio/DartDioModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dartdio/DartDioModelTest.java new file mode 100644 index 000000000000..1aa564036563 --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/dartdio/DartDioModelTest.java @@ -0,0 +1,412 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * Copyright 2018 SmartBear Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen.dartdio; + +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.Operation; +import io.swagger.v3.oas.models.media.ArraySchema; +import io.swagger.v3.oas.models.media.DateSchema; +import io.swagger.v3.oas.models.media.DateTimeSchema; +import io.swagger.v3.oas.models.media.IntegerSchema; +import io.swagger.v3.oas.models.media.MapSchema; +import io.swagger.v3.oas.models.media.Schema; +import io.swagger.v3.oas.models.media.StringSchema; +import org.openapitools.codegen.ClientOptInput; +import org.openapitools.codegen.CodegenConstants; +import org.openapitools.codegen.CodegenModel; +import org.openapitools.codegen.CodegenOperation; +import org.openapitools.codegen.CodegenProperty; +import org.openapitools.codegen.DefaultCodegen; +import org.openapitools.codegen.DefaultGenerator; +import org.openapitools.codegen.TestUtils; +import org.openapitools.codegen.config.CodegenConfigurator; +import org.openapitools.codegen.languages.DartDioClientCodegen; +import org.slf4j.LoggerFactory; +import org.testng.Assert; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +@SuppressWarnings("static-method") +public class DartDioModelTest { + + @Test(description = "convert a simple php model") + public void simpleModelTest() { + final Schema model = new Schema() + .description("a sample model") + .addProperties("id", new IntegerSchema()) + .addProperties("name", new StringSchema()) + .addProperties("createdAt", new DateTimeSchema()) + .addRequiredItem("id") + .addRequiredItem("name"); + final DefaultCodegen codegen = new DartDioClientCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", model); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel("sample", model); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a sample model"); + Assert.assertEquals(cm.vars.size(), 3); + // {{imports}} is not used in template + //Assert.assertEquals(cm.imports.size(), 1); + + final CodegenProperty property1 = cm.vars.get(0); + Assert.assertEquals(property1.baseName, "id"); + Assert.assertEquals(property1.dataType, "int"); + Assert.assertEquals(property1.name, "id"); + Assert.assertEquals(property1.defaultValue, "null"); + Assert.assertEquals(property1.baseType, "int"); + Assert.assertTrue(property1.hasMore); + Assert.assertTrue(property1.required); + Assert.assertTrue(property1.isPrimitiveType); + Assert.assertFalse(property1.isContainer); + + final CodegenProperty property2 = cm.vars.get(1); + Assert.assertEquals(property2.baseName, "name"); + Assert.assertEquals(property2.dataType, "String"); + Assert.assertEquals(property2.name, "name"); + Assert.assertEquals(property2.defaultValue, "null"); + Assert.assertEquals(property2.baseType, "String"); + Assert.assertTrue(property2.hasMore); + Assert.assertTrue(property2.required); + Assert.assertTrue(property2.isPrimitiveType); + Assert.assertFalse(property2.isContainer); + + final CodegenProperty property3 = cm.vars.get(2); + Assert.assertEquals(property3.baseName, "createdAt"); + Assert.assertEquals(property3.complexType, "DateTime"); + Assert.assertEquals(property3.dataType, "DateTime"); + Assert.assertEquals(property3.name, "createdAt"); + Assert.assertEquals(property3.defaultValue, "null"); + Assert.assertEquals(property3.baseType, "DateTime"); + Assert.assertFalse(property3.hasMore); + Assert.assertFalse(property3.required); + Assert.assertFalse(property3.isContainer); + } + + @Test(description = "convert a simple dart-dit model with datelibrary") + public void simpleModelWithTimeMachineTest() { + final Schema model = new Schema() + .description("a sample model") + .addProperties("id", new IntegerSchema()) + .addProperties("name", new StringSchema()) + .addProperties("createdAt", new DateTimeSchema()) + .addProperties("birthDate", new DateSchema()) + .addRequiredItem("id") + .addRequiredItem("name"); + + final DartDioClientCodegen codegen = new DartDioClientCodegen(); + codegen.additionalProperties().put(DartDioClientCodegen.DATE_LIBRARY, "timemachine"); + codegen.setDateLibrary("timemachine"); + codegen.processOpts(); + + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", model); + codegen.setOpenAPI(openAPI); + + final CodegenModel cm = codegen.fromModel("sample", model); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a sample model"); + Assert.assertEquals(cm.vars.size(), 4); + // {{imports}} is not used in template + //Assert.assertEquals(cm.imports.size(), 1); + + final CodegenProperty property1 = cm.vars.get(0); + Assert.assertEquals(property1.baseName, "id"); + Assert.assertEquals(property1.dataType, "int"); + Assert.assertEquals(property1.name, "id"); + Assert.assertEquals(property1.defaultValue, "null"); + Assert.assertEquals(property1.baseType, "int"); + Assert.assertTrue(property1.hasMore); + Assert.assertTrue(property1.required); + Assert.assertTrue(property1.isPrimitiveType); + Assert.assertFalse(property1.isContainer); + + final CodegenProperty property2 = cm.vars.get(1); + Assert.assertEquals(property2.baseName, "name"); + Assert.assertEquals(property2.dataType, "String"); + Assert.assertEquals(property2.name, "name"); + Assert.assertEquals(property2.defaultValue, "null"); + Assert.assertEquals(property2.baseType, "String"); + Assert.assertTrue(property2.hasMore); + Assert.assertTrue(property2.required); + Assert.assertTrue(property2.isPrimitiveType); + Assert.assertFalse(property2.isContainer); + + final CodegenProperty property3 = cm.vars.get(2); + Assert.assertEquals(property3.baseName, "createdAt"); + Assert.assertEquals(property3.complexType, "OffsetDateTime"); + Assert.assertEquals(property3.dataType, "OffsetDateTime"); + Assert.assertEquals(property3.name, "createdAt"); + Assert.assertEquals(property3.defaultValue, "null"); + Assert.assertEquals(property3.baseType, "OffsetDateTime"); + Assert.assertTrue(property3.hasMore); + Assert.assertFalse(property3.required); + Assert.assertFalse(property3.isContainer); + + final CodegenProperty property4 = cm.vars.get(3); + Assert.assertEquals(property4.baseName, "birthDate"); + Assert.assertEquals(property4.complexType, "LocalDate"); + Assert.assertEquals(property4.dataType, "LocalDate"); + Assert.assertEquals(property4.name, "birthDate"); + Assert.assertEquals(property4.defaultValue, "null"); + Assert.assertEquals(property4.baseType, "LocalDate"); + Assert.assertFalse(property4.hasMore); + Assert.assertFalse(property4.required); + Assert.assertFalse(property4.isContainer); + } + + @Test(description = "convert a model with list property") + public void listPropertyTest() { + final Schema model = new Schema() + .description("a sample model") + .addProperties("id", new IntegerSchema()) + .addProperties("urls", new ArraySchema() + .items(new StringSchema())) + .addRequiredItem("id"); + final DefaultCodegen codegen = new DartDioClientCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", model); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel("sample", model); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a sample model"); + Assert.assertEquals(cm.vars.size(), 2); + + final CodegenProperty property1 = cm.vars.get(0); + Assert.assertEquals(property1.baseName, "id"); + Assert.assertEquals(property1.dataType, "int"); + Assert.assertEquals(property1.name, "id"); + Assert.assertEquals(property1.defaultValue, "null"); + Assert.assertEquals(property1.baseType, "int"); + Assert.assertTrue(property1.hasMore); + Assert.assertTrue(property1.required); + Assert.assertTrue(property1.isPrimitiveType); + Assert.assertFalse(property1.isContainer); + + final CodegenProperty property2 = cm.vars.get(1); + Assert.assertEquals(property2.baseName, "urls"); + Assert.assertEquals(property2.dataType, "BuiltList"); + Assert.assertEquals(property2.name, "urls"); + Assert.assertEquals(property2.baseType, "BuiltList"); + Assert.assertFalse(property2.hasMore); + Assert.assertEquals(property2.containerType, "array"); + Assert.assertFalse(property2.required); + Assert.assertTrue(property2.isPrimitiveType); + Assert.assertTrue(property2.isContainer); + } + + @Test(description = "convert a model with a map property") + public void mapPropertyTest() { + final Schema model = new Schema() + .description("a sample model") + .addProperties("translations", new MapSchema() + .additionalProperties(new StringSchema())) + .addRequiredItem("id"); + final DefaultCodegen codegen = new DartDioClientCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", model); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel("sample", model); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a sample model"); + Assert.assertEquals(cm.vars.size(), 1); + + final CodegenProperty property1 = cm.vars.get(0); + Assert.assertEquals(property1.baseName, "translations"); + Assert.assertEquals(property1.dataType, "BuiltMap"); + Assert.assertEquals(property1.name, "translations"); + Assert.assertEquals(property1.baseType, "BuiltMap"); + Assert.assertEquals(property1.containerType, "map"); + Assert.assertFalse(property1.required); + Assert.assertTrue(property1.isContainer); + Assert.assertTrue(property1.isPrimitiveType); + } + + @Test(description = "convert a model with complex property") + public void complexPropertyTest() { + final Schema model = new Schema() + .description("a sample model") + .addProperties("children", new Schema().$ref("#/definitions/Children")); + final DefaultCodegen codegen = new DartDioClientCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", model); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel("sample", model); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a sample model"); + Assert.assertEquals(cm.vars.size(), 1); + + final CodegenProperty property1 = cm.vars.get(0); + Assert.assertEquals(property1.baseName, "children"); + Assert.assertEquals(property1.dataType, "Children"); + Assert.assertEquals(property1.name, "children"); + Assert.assertEquals(property1.baseType, "Children"); + Assert.assertFalse(property1.required); + Assert.assertFalse(property1.isContainer); + } + + @Test(description = "convert a model with complex list property") + public void complexListProperty() { + final Schema model = new Schema() + .description("a sample model") + .addProperties("children", new ArraySchema() + .items(new Schema().$ref("#/definitions/Children"))); + final DefaultCodegen codegen = new DartDioClientCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", model); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel("sample", model); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a sample model"); + Assert.assertEquals(cm.vars.size(), 1); + + final CodegenProperty property1 = cm.vars.get(0); + Assert.assertEquals(property1.baseName, "children"); + Assert.assertEquals(property1.dataType, "BuiltList"); + Assert.assertEquals(property1.name, "children"); + Assert.assertEquals(property1.baseType, "BuiltList"); + Assert.assertEquals(property1.containerType, "array"); + Assert.assertFalse(property1.required); + Assert.assertTrue(property1.isContainer); + } + + @Test(description = "convert a model with complex map property") + public void complexMapSchema() { + final Schema model = new Schema() + .description("a sample model") + .addProperties("children", new MapSchema() + .additionalProperties(new Schema().$ref("#/definitions/Children"))); + final DefaultCodegen codegen = new DartDioClientCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", model); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel("sample", model); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a sample model"); + Assert.assertEquals(cm.vars.size(), 1); + // {{imports}} is not used in template + //Assert.assertEquals(Sets.intersection(cm.imports, Sets.newHashSet("Children")).size(), 1); + + final CodegenProperty property1 = cm.vars.get(0); + Assert.assertEquals(property1.baseName, "children"); + Assert.assertEquals(property1.complexType, "Children"); + Assert.assertEquals(property1.dataType, "BuiltMap"); + Assert.assertEquals(property1.name, "children"); + Assert.assertEquals(property1.baseType, "BuiltMap"); + Assert.assertEquals(property1.containerType, "map"); + Assert.assertFalse(property1.required); + Assert.assertTrue(property1.isContainer); + } + + @Test(description = "convert an array model") + public void arrayModelTest() { + final Schema model = new ArraySchema() + .items(new Schema().$ref("#/definitions/Children")) + .description("an array model"); + final DefaultCodegen codegen = new DartDioClientCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", model); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel("sample", model); + + Assert.assertEquals(model.getDescription(), "an array model"); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertTrue(cm.isArrayModel); + Assert.assertEquals(cm.description, "an array model"); + Assert.assertEquals(cm.vars.size(), 0); + // skip import test as import is not used by PHP codegen + } + + @Test(description = "convert a map model") + public void mapModelTest() { + final Schema model = new Schema() + .description("a map model") + .additionalProperties(new Schema().$ref("#/definitions/Children")); + final DefaultCodegen codegen = new DartDioClientCodegen(); + OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", model); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel("sample", model); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a map model"); + Assert.assertEquals(cm.vars.size(), 0); + // {{imports}} is not used in template + //Assert.assertEquals(cm.imports.size(), 2); + //Assert.assertEquals(Sets.intersection(cm.imports, Sets.newHashSet("Children")).size(), 1); + } + + @DataProvider(name = "modelNames") + public static Object[][] primeNumbers() { + return new Object[][] { + {"sample", "Sample"}, + {"sample_name", "SampleName"}, + {"sample__name", "SampleName"}, + {"/sample", "Sample"}, + {"\\sample", "\\Sample"}, + {"sample.name", "SampleName"}, + {"_sample", "Sample"}, + }; + } + + @Test(dataProvider = "modelNames", description = "avoid inner class") + public void modelNameTest(String name, String expectedName) { + OpenAPI openAPI = TestUtils.createOpenAPI(); + final Schema model = new Schema(); + final DefaultCodegen codegen = new DartDioClientCodegen(); + codegen.setOpenAPI(openAPI); + final CodegenModel cm = codegen.fromModel(name, model); + + Assert.assertEquals(cm.name, name); + Assert.assertEquals(cm.classname, expectedName); + } + + @Test(description = "test enum variable names for reserved words") + public void testReservedWord() throws Exception { + final DefaultCodegen codegen = new DartDioClientCodegen(); + Assert.assertEquals(codegen.toEnumVarName("assert", null), "assert_"); + Assert.assertEquals(codegen.toEnumVarName("default", null), "default_"); + Assert.assertEquals(codegen.toEnumVarName("IF", null), "iF_"); + // should not escape non-reserved + Assert.assertEquals(codegen.toEnumVarName("hello", null), "hello"); + } + + // datetime (or primitive type) not yet supported in HTTP request body + @Test(description = "returns DateTime when using `--model-name-prefix`") + public void dateTest() { + final OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/2_0/datePropertyTest.json"); + final DefaultCodegen codegen = new DartDioClientCodegen(); + codegen.setModelNamePrefix("foo"); + codegen.setOpenAPI(openAPI); + + final String path = "/tests/dateResponse"; + final Operation p = openAPI.getPaths().get(path).getPost(); + final CodegenOperation op = codegen.fromOperation(path, "post", p, null); + + Assert.assertEquals(op.returnType, "DateTime"); + Assert.assertEquals(op.bodyParam.dataType, "DateTime"); + } +} diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartDioClientOptionsProvider.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartDioClientOptionsProvider.java new file mode 100644 index 000000000000..73537c6b3a1f --- /dev/null +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/options/DartDioClientOptionsProvider.java @@ -0,0 +1,69 @@ +/* + * Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech) + * Copyright 2018 SmartBear Software + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.openapitools.codegen.options; + +import com.google.common.collect.ImmutableMap; +import java.util.Map; +import org.openapitools.codegen.CodegenConstants; +import org.openapitools.codegen.languages.DartDioClientCodegen; +import org.openapitools.codegen.languages.DartDioClientCodegen; + +public class DartDioClientOptionsProvider implements OptionsProvider { + public static final String SORT_PARAMS_VALUE = "true"; + public static final String ENSURE_UNIQUE_PARAMS_VALUE = "true"; + public static final String BROWSER_CLIENT_VALUE = "true"; + public static final String PUB_NAME_VALUE = "swagger"; + public static final String PUB_VERSION_VALUE = "1.0.0-SNAPSHOT"; + public static final String PUB_DESCRIPTION_VALUE = "Swagger API client dart"; + public static final String SOURCE_FOLDER_VALUE = "src"; + public static final String USE_ENUM_EXTENSION = "true"; + public static final String ALLOW_UNICODE_IDENTIFIERS_VALUE = "false"; + public static final String PREPEND_FORM_OR_BODY_PARAMETERS_VALUE = "true"; + public static final String DATE_LIBRARY = "core"; + public static final String NULLABLE_FIELDS = "true"; + + @Override + public String getLanguage() { + return "dart"; + } + + @Override + public Map createOptions() { + ImmutableMap.Builder builder = new ImmutableMap.Builder(); + return builder.put(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_VALUE) + .put(CodegenConstants.ENSURE_UNIQUE_PARAMS, ENSURE_UNIQUE_PARAMS_VALUE) + .put(DartDioClientCodegen.BROWSER_CLIENT, BROWSER_CLIENT_VALUE) + .put(DartDioClientCodegen.PUB_NAME, PUB_NAME_VALUE) + .put(DartDioClientCodegen.PUB_VERSION, PUB_VERSION_VALUE) + .put(DartDioClientCodegen.PUB_DESCRIPTION, PUB_DESCRIPTION_VALUE) + .put(CodegenConstants.SOURCE_FOLDER, SOURCE_FOLDER_VALUE) + .put(DartDioClientCodegen.USE_ENUM_EXTENSION, USE_ENUM_EXTENSION) + .put(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, ALLOW_UNICODE_IDENTIFIERS_VALUE) + .put(CodegenConstants.PREPEND_FORM_OR_BODY_PARAMETERS, PREPEND_FORM_OR_BODY_PARAMETERS_VALUE) + .put(DartDioClientCodegen.SUPPORT_DART2, "false") + .put(DartDioClientCodegen.DATE_LIBRARY, DATE_LIBRARY) + .put(DartDioClientCodegen.NULLABLE_FIELDS, NULLABLE_FIELDS) + + .build(); + } + + @Override + public boolean isServer() { + return false; + } +}