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
1 change: 0 additions & 1 deletion bin/configs/kotlin-server-jaxrs-spec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,4 @@ inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-server
additionalProperties:
useCoroutines: "true"
useTags: "true"
implicitHeaders: "true"
9 changes: 9 additions & 0 deletions bin/configs/kotlin-server-ktor2-usetags-false.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
generatorName: kotlin-server
outputDir: samples/server/petstore/kotlin-server/ktor2-usetags-false
library: ktor2
inputSpec: modules/openapi-generator/src/test/resources/3_0/kotlin/petstore-with-tags.yaml
templateDir: modules/openapi-generator/src/main/resources/kotlin-server
additionalProperties:
hideGenerationTimestamp: "true"
serializableModel: "true"
useTags: "false"
2 changes: 1 addition & 1 deletion docs/generators/kotlin-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|useCoroutines|Whether to use the Coroutines. This option is currently supported only when using jaxrs-spec library.| |false|
|useJakartaEe|whether to use Jakarta EE namespace instead of javax| |false|
|useMutiny|Whether to use Mutiny (should not be used with useCoroutines). This option is currently supported only when using jaxrs-spec library.| |false|
|useTags|use tags for creating interface and controller classnames| |false|
|useTags|use tags for creating interface and controller classnames.| |true|

## IMPORT MAPPING

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,6 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
public static final String JACKSON2_PACKAGE = "com.fasterxml.jackson";
public static final String JACKSON3_PACKAGE = "tools.jackson";
public static final String JACKSON_PACKAGE = "jacksonPackage";
public static final String USE_TAGS = "useTags";
public static final String USE_TAGS_DESC = "use tags for creating interface and controller classnames";
public static final String SCHEMA_IMPLEMENTS = "schemaImplements";
public static final String SCHEMA_IMPLEMENTS_FIELDS = "schemaImplementsFields";
public static final String X_KOTLIN_IMPLEMENTS_SKIP = "xKotlinImplementsSkip";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,35 @@

package org.openapitools.codegen.languages;

import com.google.common.collect.ImmutableMap;
import io.swagger.v3.oas.models.Operation;
import java.io.File;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import lombok.Getter;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.CodegenConstants;
import org.openapitools.codegen.CodegenDiscriminator;
import org.openapitools.codegen.CodegenModel;
import org.openapitools.codegen.CodegenOperation;
import org.openapitools.codegen.CodegenParameter;
import org.openapitools.codegen.CodegenProperty;
import org.openapitools.codegen.CodegenResponse;
import org.openapitools.codegen.CodegenType;
import org.openapitools.codegen.SupportingFile;
import org.openapitools.codegen.languages.features.BeanValidationFeatures;
import org.openapitools.codegen.meta.features.*;
import org.openapitools.codegen.meta.features.DocumentationFeature;
import org.openapitools.codegen.meta.features.GlobalFeature;
import org.openapitools.codegen.meta.features.ParameterFeature;
import org.openapitools.codegen.meta.features.SchemaSupportFeature;
import org.openapitools.codegen.meta.features.SecurityFeature;
import org.openapitools.codegen.meta.features.WireFormatFeature;
import org.openapitools.codegen.model.ModelMap;
import org.openapitools.codegen.model.ModelsMap;
import org.openapitools.codegen.model.OperationMap;
Expand All @@ -33,8 +55,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.util.*;
import static org.openapitools.codegen.languages.KotlinServerCodegen.Constants.USE_TAGS;

public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanValidationFeatures {

Expand Down Expand Up @@ -64,7 +85,7 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanVa
private Boolean metricsFeatureEnabled = true;
private boolean interfaceOnly = false;
private boolean useBeanValidation = false;
private boolean useTags = false;
private boolean useTags = true;
private boolean useCoroutines = false;
private boolean useMutiny = false;
private boolean returnResponse = false;
Expand All @@ -74,38 +95,6 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanVa
@Setter
private boolean fixJacksonJsonTypeInfoInheritance = true;

// This is here to potentially warn the user when an option is not supported by the target framework.
private Map<String, List<String>> optionsSupportedPerFramework = new ImmutableMap.Builder<String, List<String>>()
.put(Constants.KTOR, Arrays.asList(
Constants.AUTOMATIC_HEAD_REQUESTS,
Constants.CONDITIONAL_HEADERS,
Constants.HSTS,
Constants.CORS,
Constants.COMPRESSION,
Constants.RESOURCES,
Constants.METRICS,
Constants.OMIT_GRADLE_WRAPPER
))
.put(Constants.KTOR2, Arrays.asList(
Constants.AUTOMATIC_HEAD_REQUESTS,
Constants.CONDITIONAL_HEADERS,
Constants.HSTS,
Constants.CORS,
Constants.COMPRESSION,
Constants.RESOURCES,
Constants.METRICS,
Constants.OMIT_GRADLE_WRAPPER
))
.put(Constants.JAXRS_SPEC, Arrays.asList(
USE_BEANVALIDATION,
USE_TAGS,
Constants.USE_COROUTINES,
Constants.USE_MUTINY,
Constants.RETURN_RESPONSE,
Constants.INTERFACE_ONLY
))
.build();

/**
* Constructs an instance of `KotlinServerCodegen`.
*/
Expand Down Expand Up @@ -172,7 +161,7 @@ public KotlinServerCodegen() {
addSwitch(Constants.METRICS, Constants.METRICS_DESC, getMetricsFeatureEnabled());
addSwitch(Constants.INTERFACE_ONLY, Constants.INTERFACE_ONLY_DESC, interfaceOnly);
addSwitch(USE_BEANVALIDATION, Constants.USE_BEANVALIDATION_DESC, useBeanValidation);
addSwitch(USE_TAGS, USE_TAGS_DESC, useTags);
addSwitch(USE_TAGS, Constants.USE_TAGS_DESC, useTags);
addSwitch(Constants.USE_COROUTINES, Constants.USE_COROUTINES_DESC, useCoroutines);
addSwitch(Constants.USE_MUTINY, Constants.USE_MUTINY_DESC, useMutiny);
addSwitch(Constants.RETURN_RESPONSE, Constants.RETURN_RESPONSE_DESC, returnResponse);
Expand Down Expand Up @@ -405,6 +394,8 @@ public static class Constants {
public static final String IS_KTOR = "isKtor";
public static final String FIX_JACKSON_JSON_TYPE_INFO_INHERITANCE = "fixJacksonJsonTypeInfoInheritance";
public static final String FIX_JACKSON_JSON_TYPE_INFO_INHERITANCE_DESC = "When true (default), ensures Jackson polymorphism works correctly by: (1) always setting visible=true on @JsonTypeInfo, and (2) adding the discriminator property to child models with appropriate default values. When false, visible is only set to true if all children already define the discriminator property.";
public static final String USE_TAGS = "useTags";
public static final String USE_TAGS_DESC = "use tags for creating interface and controller classnames.";
}

@Override
Expand Down Expand Up @@ -702,32 +693,40 @@ public void postProcess() {
System.out.println("################################################################################");
}

@Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
if (useTags) {
super.addOperationToGroup(tag, resourcePath, operation, co, operations);
return;
}

String basePath = StringUtils.substringBefore(resourcePath.startsWith("/") ? resourcePath.substring(1) : resourcePath, "/");
if (StringUtils.isEmpty(basePath) || basePath.chars().anyMatch(ch -> ch == '{' || ch == '}')) {
basePath = "default";
}
super.addOperationToGroup(basePath, resourcePath, operation, co, operations);
}

@Override
public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<ModelMap> allModels) {
OperationMap operations = objs.getOperations();
// For JAXRS_SPEC library, compute commonPath when useTags=true, otherwise default to "/"
// For JAXRS_SPEC library, compute commonPath for all library modes
if (operations != null && Objects.equals(library, Constants.JAXRS_SPEC)) {
if (useTags) {
String commonPath = null;
List<CodegenOperation> ops = operations.getOperation();
for (CodegenOperation operation : ops) {
if (commonPath == null) {
commonPath = operation.path;
} else {
commonPath = getCommonPath(commonPath, operation.path);
}
}
for (CodegenOperation co : ops) {
co.path = StringUtils.removeStart(co.path, commonPath);
co.subresourceOperation = co.path.length() > 1;
}
objs.put("commonPath", "/".equals(commonPath) ? StringUtils.EMPTY : commonPath);
} else {
for (CodegenOperation co : operations.getOperation()) {
co.subresourceOperation = !co.path.isEmpty();
List<CodegenOperation> ops = operations.getOperation();
// Compute commonPath from operations in this group (called once per API class)
String commonPath = null;
for (CodegenOperation operation : ops) {
if (commonPath == null) {
commonPath = operation.path;
} else {
commonPath = getCommonPath(commonPath, operation.path);
}
objs.put("commonPath", "/");
}
for (CodegenOperation co : ops) {
co.path = StringUtils.removeStart(co.path, commonPath);
co.subresourceOperation = co.path.length() > 1;
}
objs.put("commonPath", "/".equals(commonPath) ? StringUtils.EMPTY : commonPath);
}
// The following processing breaks the JAX-RS spec, so we only do this for the other libs.
if (operations != null && !Objects.equals(library, Constants.JAXRS_SPEC)) {
Expand Down Expand Up @@ -801,8 +800,8 @@ private boolean isJavalin() {
*/
private boolean usesJacksonSerialization() {
return Constants.JAVALIN5.equals(library) ||
Constants.JAVALIN6.equals(library) ||
Constants.JAXRS_SPEC.equals(library);
Constants.JAVALIN6.equals(library) ||
Constants.JAXRS_SPEC.equals(library);
}

private boolean isKtor2Or3() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ All URIs are relative to *{{{basePath}}}*

Class | Method | HTTP request | Description
------------ | ------------- | ------------- | -------------
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{#useTags}}{{commonPath}}{{/useTags}}{{path}} | {{{summary}}}
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{commonPath}}{{path}} | {{{summary}}}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems operationIdLowerCase is not set in the useTags=false case - probably because the super method that sets it is never called.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice catch, fixed in c3e559b

{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
{{/generateApiDocs}}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@{{httpMethod}}
@Path("{{{path}}}"){{#hasConsumes}}
@{{httpMethod}}{{#subresourceOperation}}
@Path("{{{path}}}"){{/subresourceOperation}}{{#hasConsumes}}
@Consumes({{#consumes}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/consumes}}){{/hasConsumes}}{{#hasProduces}}
@Produces({{#produces}}"{{{mediaType}}}"{{^-last}}, {{/-last}}{{/produces}}){{/hasProduces}}
{{#useCoroutines}}suspend {{/useCoroutines}}fun {{nickname}}({{#allParams}}{{>queryParams}}{{>pathParams}}{{>headerParams}}{{>bodyParams}}{{>formParams}}{{^-last}},{{/-last}}{{/allParams}}){{#returnResponse}}: {{#useMutiny}}io.smallrye.mutiny.Uni<{{/useMutiny}}Response{{#useMutiny}}>{{/useMutiny}}{{/returnResponse}}{{^returnResponse}}{{#returnType}}: {{#useMutiny}}io.smallrye.mutiny.Uni<{{/useMutiny}}{{{returnType}}}{{#useMutiny}}>{{/useMutiny}}{{/returnType}}{{/returnResponse}}{{^returnResponse}}{{^returnType}}{{#useMutiny}}: io.smallrye.mutiny.Uni<Void>{{/useMutiny}}{{/returnType}}{{/returnResponse}}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ import {{packageName}}.infrastructure.ApiPrincipal

{{#operations}}
fun Route.{{classname}}() {
val empty = mutableMapOf<String, Any?>()
{{#operation}}
{{#hasAuthMethods}}
{{#authMethods}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ val exampleContentType = "{{{contentType}}}"
val exampleContentString = """{{&example}}"""

when (exampleContentType) {
"application/json" -> call.respond(gson.fromJson(exampleContentString, empty::class.java))
"application/json" -> call.respond(gson.fromJson(exampleContentString, Any::class.java))
"application/xml" -> call.respondText(exampleContentString, ContentType.Text.Xml)
else -> call.respondText(exampleContentString)
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ import {{packageName}}.infrastructure.ApiPrincipal
{{#operations}}
fun Route.{{classname}}() {
val gson = Gson()
val empty = mutableMapOf<String, Any?>()
{{#operation}}
{{#hasAuthMethods}}
{{#authMethods}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>

Expand Down
Loading
Loading