Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ public class ScalaSttp4ClientCodegen extends AbstractScalaCodegen implements Cod
protected boolean renderJavadoc = true;
protected boolean removeOAuthSecurities = true;

Map<String, ModelsMap> enumRefs = new HashMap<>();

public ScalaSttp4ClientCodegen() {
super();
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
Expand Down Expand Up @@ -507,7 +505,6 @@ private void propagateParentProperties(CodegenModel childModel, List<CodegenProp
/**
* Update/clean up model imports
* <p>
* append '._" if the import is a Enum class, otherwise
* remove model imports to avoid warnings for importing class in the same package in Scala
*
* @param models processed models to be further processed
Expand All @@ -516,8 +513,6 @@ private void propagateParentProperties(CodegenModel childModel, List<CodegenProp
private void postProcessUpdateImports(final Map<String, ModelsMap> models) {
final String prefix = modelPackage() + ".";

enumRefs = getEnumRefs(models);

for (String openAPIName : models.keySet()) {
CodegenModel model = ModelUtils.getModelByName(openAPIName, models);
if (model == null) {
Expand All @@ -534,13 +529,11 @@ private void postProcessUpdateImports(final Map<String, ModelsMap> models) {
Iterator<Map<String, String>> iterator = imports.iterator();
while (iterator.hasNext()) {
String importPath = iterator.next().get("import");
Map<String, String> item = new HashMap<>();
if (importPath.startsWith(prefix)) {
if (isEnumClass(importPath, enumRefs)) {
item.put("import", importPath.concat("._"));
newImports.add(item);
}
} else {
// Same-package imports are dropped: sttp4 enums are sealed traits +
// case objects (not Enumeration), so unlike scala-sttp there is no
// `MyEnum._` wildcard needed to bring a type alias into scope.
if (!importPath.startsWith(prefix)) {
Map<String, String> item = new HashMap<>();
item.put("import", importPath);
newImports.add(item);
}
Expand All @@ -550,37 +543,6 @@ private void postProcessUpdateImports(final Map<String, ModelsMap> models) {
}
}

private Map<String, ModelsMap> getEnumRefs(final Map<String, ModelsMap> models) {
Map<String, ModelsMap> enums = new HashMap<>();
for (String key : models.keySet()) {
CodegenModel model = ModelUtils.getModelByName(key, models);
if (model.isEnum) {
ModelsMap objs = models.get(key);
enums.put(key, objs);
}
}
return enums;
}

private boolean isEnumClass(final String importPath, final Map<String, ModelsMap> enumModels) {
if (enumModels == null || enumModels.isEmpty()) {
return false;
}
for (ModelsMap objs : enumModels.values()) {
List<ModelMap> models = objs.getModels();
if (models == null || models.isEmpty()) {
continue;
}
for (final Map<String, Object> model : models) {
String enumImportPath = (String) model.get("importPath");
if (enumImportPath != null && enumImportPath.equals(importPath)) {
return true;
}
}
}
return false;
}

@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> allModels) {
if (registerNonStandardStatusCodes) {
Expand Down Expand Up @@ -618,11 +580,10 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
while (iterator.hasNext()) {
String importPath = iterator.next().get("import");
Map<String, String> item = new HashMap<>();
if (isEnumClass(importPath, enumRefs)) {
item.put("import", importPath.concat("._"));
} else {
item.put("import", importPath);
}
// sttp4 enums are sealed traits + case objects (not Enumeration):
// import the type itself, not `MyEnum._` wildcard members, which
// would not bring the type into scope.
item.put("import", importPath);
newImports.add(item);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ sealed trait {{classname}}
object {{classname}} {
{{#allowableValues}}
{{#values}}
case object {{#fnEnumEntry}}{{.}}{{/fnEnumEntry}} extends {{classname}}
case object {{#fnEnumEntry}}{{.}}{{/fnEnumEntry}} extends {{classname}} { override def toString: String = "{{.}}" }
{{/values}}
{{/allowableValues}}

Expand Down Expand Up @@ -338,7 +338,7 @@ object {{classname}}Enums {
sealed trait {{datatypeWithEnum}}
object {{datatypeWithEnum}} {
{{#_enum}}
case object {{#fnEnumEntry}}{{.}}{{/fnEnumEntry}} extends {{datatypeWithEnum}}
case object {{#fnEnumEntry}}{{.}}{{/fnEnumEntry}} extends {{datatypeWithEnum}} { override def toString: String = "{{.}}" }
{{/_enum}}

{{#circe}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,50 @@ public void verifyApiKeyLocations() throws IOException {
assertFileContains(path, ".cookie(\"apikey\", apiKeyCookie)");
}

@Test
public void verifyEnumParameterImportAndWireValues() 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/sttp4-enum-param.yaml", null, new ParseOptions()).getOpenAPI();

ScalaSttp4ClientCodegen codegen = new ScalaSttp4ClientCodegen();
codegen.setOutputDir(output.getAbsolutePath());
codegen.additionalProperties().put("jsonLibrary", "circe");

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, "true");
generator.setGeneratorPropertyDefault(CodegenConstants.SUPPORTING_FILES, "false");
generator.opts(input).generate();

// Enums are sealed traits + case objects: the API must import the type itself,
// not Enumeration-style wildcard members (which would not bring the type into scope).
Path apiPath = Paths.get(outputPath + "/src/main/scala/org/openapitools/client/api/DefaultApi.scala");
assertFileContains(apiPath, "import org.openapitools.client.model.PetStatus\n");
assertFileNotContains(apiPath, "import org.openapitools.client.model.PetStatus._");

// Models live in the same package as the enum: no import is needed at all
// (sealed trait, not an Enumeration with a type alias inside the companion).
Path modelPath = Paths.get(outputPath + "/src/main/scala/org/openapitools/client/model/Pet.scala");
assertFileNotContains(modelPath, "import org.openapitools.client.model.PetStatus");

// Case objects carry their wire value as toString so path/query interpolation
// (uri"...${param}...") serializes the wire value, not the Scala identifier.
Path enumPath = Paths.get(outputPath + "/src/main/scala/org/openapitools/client/model/PetStatus.scala");
assertFileContains(enumPath, "case object Available extends PetStatus { override def toString: String = \"available\" }");
assertFileContains(enumPath, "case object SoldOut extends PetStatus { override def toString: String = \"sold-out\" }");
}

@Test
public void verifyOneOfSupportWithCirce() throws IOException {
File output = Files.createTempDirectory("test").toFile().getCanonicalFile();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
openapi: 3.0.3
info:
title: Enum parameter test
version: 1.0.0
paths:
/pets/{status}:
get:
operationId: getPetsByStatus
parameters:
- name: status
in: path
required: true
schema:
$ref: '#/components/schemas/PetStatus'
responses:
'200':
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
components:
schemas:
PetStatus:
type: string
enum:
- available
- pending
- sold-out
Pet:
type: object
required:
- name
properties:
name:
type: string
status:
$ref: '#/components/schemas/PetStatus'
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ object OrderEnums {

sealed trait Status
object Status {
case object Placed extends Status
case object Approved extends Status
case object Delivered extends Status
case object Placed extends Status { override def toString: String = "placed" }
case object Approved extends Status { override def toString: String = "approved" }
case object Delivered extends Status { override def toString: String = "delivered" }

import io.circe.{Encoder, Decoder}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ object PetEnums {

sealed trait Status
object Status {
case object Available extends Status
case object Pending extends Status
case object Sold extends Status
case object Available extends Status { override def toString: String = "available" }
case object Pending extends Status { override def toString: String = "pending" }
case object Sold extends Status { override def toString: String = "sold" }

import io.circe.{Encoder, Decoder}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ object OrderEnums {

sealed trait Status
object Status {
case object Placed extends Status
case object Approved extends Status
case object Delivered extends Status
case object Placed extends Status { override def toString: String = "placed" }
case object Approved extends Status { override def toString: String = "approved" }
case object Delivered extends Status { override def toString: String = "delivered" }

import org.json4s._

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ object PetEnums {

sealed trait Status
object Status {
case object Available extends Status
case object Pending extends Status
case object Sold extends Status
case object Available extends Status { override def toString: String = "available" }
case object Pending extends Status { override def toString: String = "pending" }
case object Sold extends Status { override def toString: String = "sold" }

import org.json4s._

Expand Down
Loading