diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java index 15c73855e142..d453d882e57b 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractScalaCodegen.java @@ -47,6 +47,9 @@ public abstract class AbstractScalaCodegen extends DefaultCodegen { private final Logger LOGGER = LoggerFactory.getLogger(AbstractScalaCodegen.class); + // https://spec.openapis.org/registry/format/date-time-local.html + protected static final String DATE_TIME_LOCAL_FORMAT = "date-time-local"; + @Getter protected String modelPropertyNaming = CodegenConstants.ENUM_PROPERTY_NAMING_TYPE.camelCase.name(); @Setter protected String invokerPackage = "org.openapitools.client"; @Getter @Setter @@ -137,6 +140,7 @@ public AbstractScalaCodegen() { // Scala specific openApi types mapping typeMapping.put("ByteArray", "Array[Byte]"); + typeMapping.put(DATE_TIME_LOCAL_FORMAT, "LocalDateTime"); importMapping = new HashMap(); @@ -226,8 +230,10 @@ public void processOpts() { if (additionalProperties.containsKey(DATE_LIBRARY)) { this.setDateLibrary(additionalProperties.get(DATE_LIBRARY).toString(), false); } + this.typeMapping.put(DATE_TIME_LOCAL_FORMAT, "LocalDateTime"); if (DateLibraries.java8.name().equals(dateLibrary)) { this.importMapping.put("LocalDate", "java.time.LocalDate"); + this.importMapping.put("LocalDateTime", "java.time.LocalDateTime"); this.importMapping.put("OffsetDateTime", "java.time.OffsetDateTime"); this.typeMapping.put("date", "LocalDate"); this.typeMapping.put("DateTime", "OffsetDateTime"); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/scala/AbstractScalaCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/scala/AbstractScalaCodegenTest.java index 7c3b9f0c416f..7a08a568467c 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/scala/AbstractScalaCodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/scala/AbstractScalaCodegenTest.java @@ -100,6 +100,27 @@ public void checkScalaTypeImportMapping() { "BigInt is a Scala type and must not be imported"); } + @Test + void checkDateTimeLocalTypeMappingJava8() { + P_AbstractScalaCodegen codegen = new P_AbstractScalaCodegen(); + codegen.processOpts(); + Assert.assertEquals(codegen.typeMapping().get("date-time-local"), "LocalDateTime", + "date-time-local format should map to LocalDateTime"); + Assert.assertEquals(codegen.importMapping().get("LocalDateTime"), "java.time.LocalDateTime", + "LocalDateTime should import from java.time when using java8 date library"); + } + + @Test + void checkDateTimeLocalTypeDeclaration() { + P_AbstractScalaCodegen codegen = new P_AbstractScalaCodegen(); + codegen.processOpts(); + Schema schema = new ObjectSchema(); + schema.setType("string"); + schema.setFormat("date-time-local"); + Assert.assertEquals(codegen.getTypeDeclaration(schema), "LocalDateTime", + "Schema with date-time-local format should produce LocalDateTime type"); + } + @Test void checkTypeDeclarationWithByteString() { Schema byteArraySchema = new ObjectSchema(); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/scala/Sttp4CodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/scala/Sttp4CodegenTest.java index 74f7f43ae1e1..2e74ec6de7eb 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/scala/Sttp4CodegenTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/scala/Sttp4CodegenTest.java @@ -53,4 +53,40 @@ public void verifyApiKeyLocations() throws IOException { assertFileContains(path, ".header(\"X-Api-Key\", apiKeyHeader)"); assertFileContains(path, ".cookie(\"apikey\", apiKeyCookie)"); } + + @Test + public void verifyDateTimeLocalGeneratesLocalDateTime() throws IOException { + File output = Files.createTempDirectory("test").toFile().getCanonicalFile(); + output.deleteOnExit(); + String outputPath = output.getAbsolutePath().replace('\\', '/'); + + OpenAPI openAPI = new OpenAPIParser() + .readLocation("src/test/resources/3_0/scala/date-time-local.yaml", null, new ParseOptions()).getOpenAPI(); + + ScalaSttp4ClientCodegen codegen = new ScalaSttp4ClientCodegen(); + codegen.setOutputDir(output.getAbsolutePath()); + + ClientOptInput input = new ClientOptInput(); + input.openAPI(openAPI); + input.config(codegen); + + DefaultGenerator generator = new DefaultGenerator(); + + generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true"); + generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_TESTS, "false"); + generator.setGeneratorPropertyDefault(CodegenConstants.MODEL_DOCS, "false"); + generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "false"); + generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false"); + generator.opts(input).generate(); + + Path modelPath = Paths.get(outputPath + "/src/main/scala/org/openapitools/client/model/Event.scala"); + // date-time-local maps to LocalDateTime + assertFileContains(modelPath, "import java.time.LocalDateTime"); + assertFileContains(modelPath, "startTime: LocalDateTime"); + assertFileContains(modelPath, "endTime: Option[LocalDateTime]"); + // date-time maps to OffsetDateTime + assertFileContains(modelPath, "import java.time.OffsetDateTime"); + assertFileContains(modelPath, "createdAt: OffsetDateTime"); + assertFileContains(modelPath, "updatedAt: Option[OffsetDateTime]"); + } } diff --git a/modules/openapi-generator/src/test/resources/3_0/scala/date-time-local.yaml b/modules/openapi-generator/src/test/resources/3_0/scala/date-time-local.yaml new file mode 100644 index 000000000000..63f3a1e26f44 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/scala/date-time-local.yaml @@ -0,0 +1,41 @@ +openapi: 3.0.3 +info: + title: Date Time Local Test API + version: 1.0.0 +paths: + /events: + get: + operationId: getEvents + summary: Get events + responses: + '200': + description: Successful response + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Event' +components: + schemas: + Event: + type: object + required: + - name + - startTime + - createdAt + properties: + name: + type: string + startTime: + type: string + format: date-time-local + endTime: + type: string + format: date-time-local + createdAt: + type: string + format: date-time + updatedAt: + type: string + format: date-time