Skip to content

Commit

Permalink
Add configuration option for a custom template directory (#801)
Browse files Browse the repository at this point in the history
  • Loading branch information
FelixScherzinger authored Oct 1, 2024
1 parent 91eddd5 commit ae8bbff
Show file tree
Hide file tree
Showing 10 changed files with 546 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public enum ConfigName {
//global configs
VERBOSE("verbose"),
INPUT_BASE_DIR("input-base-dir"),
TEMPLATE_BASE_DIR("template-base-dir"),
INCLUDE("include"),
EXCLUDE("exclude"),
VALIDATE_SPEC("validateSpec"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ public class GlobalCodegenConfig extends CommonItemConfig {
@ConfigItem(name = "input-base-dir")
public Optional<String> inputBaseDir;

/**
* Option to change the directory where template files must be found.
*/
@ConfigItem(name = "template-base-dir")
public Optional<String> templateBaseDir;

/**
* Whether or not to skip validating the input spec prior to generation. By default, invalid specifications will result in
* an error.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import static io.quarkiverse.openapi.generator.deployment.CodegenConfig.ConfigName.INPUT_BASE_DIR;
import static io.quarkiverse.openapi.generator.deployment.CodegenConfig.ConfigName.MODEL_NAME_PREFIX;
import static io.quarkiverse.openapi.generator.deployment.CodegenConfig.ConfigName.MODEL_NAME_SUFFIX;
import static io.quarkiverse.openapi.generator.deployment.CodegenConfig.ConfigName.TEMPLATE_BASE_DIR;
import static io.quarkiverse.openapi.generator.deployment.CodegenConfig.ConfigName.VALIDATE_SPEC;

import java.io.IOException;
Expand Down Expand Up @@ -119,7 +120,9 @@ public boolean trigger(CodeGenContext context) throws CodeGenException {
}

try (Stream<Path> openApiFilesPaths = Files.walk(openApiDir)) {
Path templateDir = context.workDir().resolve("classes").resolve("templates");
Optional<String> templateBaseDir = getTemplateBaseDirRelativeToSourceRoot(context.inputDir(), context.config());
Path templateDir = templateBaseDir.map(Path::of)
.orElseGet(() -> context.workDir().resolve("classes").resolve("templates"));
openApiFilesPaths
.filter(Files::isRegularFile)
.filter(path -> {
Expand Down Expand Up @@ -318,9 +321,16 @@ private Optional<String> getModelNamePrefix(final Config config, final Path open
}

private Optional<String> getInputBaseDirRelativeToModule(final Path sourceDir, final Config config) {
return config.getOptionalValue(getGlobalConfigName(INPUT_BASE_DIR), String.class).map(inputBaseDir -> {
return config.getOptionalValue(getGlobalConfigName(INPUT_BASE_DIR), String.class).map(baseDir -> {
int srcIndex = sourceDir.toString().lastIndexOf("src");
return srcIndex < 0 ? null : sourceDir.toString().substring(0, srcIndex) + inputBaseDir;
return srcIndex < 0 ? null : sourceDir.toString().substring(0, srcIndex) + baseDir;
});
}

private Optional<String> getTemplateBaseDirRelativeToSourceRoot(final Path sourceDir, final Config config) {
return config.getOptionalValue(getGlobalConfigName(TEMPLATE_BASE_DIR), String.class).map(baseDir -> {
int srcIndex = sourceDir.toString().lastIndexOf(inputDirectory());
return srcIndex < 0 ? null : sourceDir.toString().substring(0, srcIndex) + baseDir;
});
}

Expand Down
94 changes: 94 additions & 0 deletions client/integration-tests/change-custom-template-directory/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>quarkus-openapi-generator-integration-tests</artifactId>
<groupId>io.quarkiverse.openapi.generator</groupId>
<version>3.0.0-SNAPSHOT</version>
</parent>
<artifactId>quarkus-openapi-generator-it-change-custom-template-directory</artifactId>
<name>Quarkus - Openapi Generator - Integration Tests - Client - Change custom template directory</name>

<dependencies>
<dependency>
<groupId>io.quarkiverse.openapi.generator</groupId>
<artifactId>quarkus-openapi-generator</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkiverse.openapi.generator</groupId>
<artifactId>quarkus-openapi-generator-test-utils</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-maven-plugin</artifactId>
<extensions>true</extensions>
<executions>
<execution>
<goals>
<goal>build</goal>
<goal>generate-code</goal>
<goal>generate-code-tests</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>native-image</id>
<activation>
<property>
<name>native</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>${native.surefire.skip}</skipTests>
</configuration>
</plugin>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemPropertyVariables>
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<quarkus.package.type>native</quarkus.package.type>
</properties>
</profile>
</profiles>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package {package};

{#for imp in imports}
import {imp.import};
{/for}
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
{#if hasAuthMethods || custom-register-providers.orEmpty.size > 0}
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
{/if}
{#if hasAuthMethods}
import org.eclipse.microprofile.rest.client.annotation.RegisterClientHeaders;
import {package}.auth.CompositeAuthenticationProvider;
{#if client-headers-factory is 'default'}
import {package}.auth.AuthenticationPropagationHeadersFactory;
{/if}
{/if}

import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;

import jakarta.enterprise.context.ApplicationScoped;

import io.quarkiverse.openapi.generator.annotations.GeneratedClass;
import io.quarkiverse.openapi.generator.annotations.GeneratedMethod;
import io.quarkiverse.openapi.generator.annotations.GeneratedParam;

{#if appName}
/**
* {appName}
* {#if appDescription}<p>{appDescription}</p>{/if}
*/
{/if}
@Path("{#if useAnnotatedBasePath}{contextPath}{/if}{commonPath}")
@RegisterRestClient({#if defaultServerUrl}baseUri="{defaultServerUrl}",{/if}configKey="{configKey}")
@GeneratedClass(value="{openapi:parseUri(inputSpec)}", tag = "{baseName}")
{#if hasAuthMethods}
@RegisterProvider(CompositeAuthenticationProvider.class)
{#when client-headers-factory}
{#is 'default'}
@RegisterClientHeaders(AuthenticationPropagationHeadersFactory.class)
{#is 'none'}
@RegisterClientHeaders
{#else}
@RegisterClientHeaders({client-headers-factory}.class)
{/when}
{/if}
{#for crpClassConfig in custom-register-providers.orEmpty}
@RegisterProvider({crpClassConfig}.class)
{/for}
@ApplicationScoped
public interface {classname} {

public default void myCustomMethod() {
}

{#for op in operations.operation}
{#if !op.isDeprecated || openapi:genDeprecatedApiAttr(package, classname, classes-codegen)}
{#if op.summary}
/**
* {op.summary}
*
{#if op.notes}
* {op.notes}
*
{/if}
*/
{/if}
@{op.httpMethod}
{#if op.subresourceOperation}
@Path("{op.path}")
{/if}
{#if op.hasConsumes}
@Consumes(\{{#for consume in op.consumes}"{consume.mediaType}"{#if consume_hasNext}, {/if}{/for}\})
{/if}
{#if op.hasProduces}
@Produces(\{{#for produce in op.produces}"{produce.mediaType}"{#if produce_hasNext}, {/if}{/for}\})
{/if}
@GeneratedMethod ("{op.operationIdOriginal}")
{#for cbClassConfig in circuit-breaker.orEmpty}{#if cbClassConfig.key == package + classname}
{#for cbMethod in cbClassConfig.value.orEmpty}{#if cbMethod == op.nickname}
@org.eclipse.microprofile.faulttolerance.CircuitBreaker
{/if}{/for}
{/if}{/for}
{#if mutiny}
{#if return-response}
public io.smallrye.mutiny.Uni<jakarta.ws.rs.core.Response> {op.nickname}(
{#else}
{#if op.returnType == "void"}
public {#if op.returnType}io.smallrye.mutiny.Uni<Void>{#else}io.smallrye.mutiny.Uni<jakarta.ws.rs.core.Response>{/if} {op.nickname}(
{#else}
public {#if op.returnType}io.smallrye.mutiny.Uni<{op.returnType}>{#else}io.smallrye.mutiny.Uni<jakarta.ws.rs.core.Response>{/if} {op.nickname}(
{/if}
{/if}
{#else}
{#if return-response}
public jakarta.ws.rs.core.Response {op.nickname}(
{#else}
public {#if op.returnType}{op.returnType}{#else}jakarta.ws.rs.core.Response{/if} {op.nickname}(
{/if}
{/if}
{#if op.hasFormParams}
{#if is-resteasy-reactive}
@jakarta.ws.rs.BeanParam {op.operationIdCamelCase}MultipartForm multipartForm{#if op.hasPathParams},{/if}{!
!}{#for p in op.pathParams}{#include templates.path_params param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasQueryParams},{/if}{!
!}{#for p in op.queryParams}{#include templates.query_params param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasBodyParams},{/if}{!
!}{#for p in op.bodyParams}{#include bodyParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasHeaderParams},{/if}{!
!}{#for p in op.headerParams}{#include headerParams.qute param=p/}{#if p_hasNext}, {/if}{/for}
{#else}
@org.jboss.resteasy.annotations.providers.multipart.MultipartForm {op.operationIdCamelCase}MultipartForm multipartForm{#if op.hasPathParams},{/if}{!
!}{#for p in op.pathParams}{#include pathParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasQueryParams},{/if}{!
!}{#for p in op.queryParams}{#include queryParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasBodyParams},{/if}{!
!}{#for p in op.bodyParams}{#include bodyParams.qute param=p/}{#if p_hasNext}, {/if}{/for}{#if op.hasHeaderParams},{/if}{!
!}{#for p in op.headerParams}{#include headerParams.qute param=p/}{#if p_hasNext}, {/if}{/for}
{/if}
{#else}
{#for p in op.allParams}
{#if p.hasValidation}@jakarta.validation.Valid {/if}{#include pathParams.qute param=p/}{#include queryParams.qute param=p/}{#include bodyParams.qute param=p/}{#include headerParams.qute param=p/}{#if p_hasNext}, {/if}
{/for}
{/if}
);
{#if op.hasFormParams}

{#include multipartFormdataPojo.qute param=op/}
{/if}

{/if} {! check deprecated !}
{/for}
}
Loading

0 comments on commit ae8bbff

Please sign in to comment.