Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JAVA] new Feature interface: Documentation Provider and Annotation Library #11258

Merged
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9865887
Implement DocumentationProviderFeatures and integrate it in AbstractJ…
cachescrubber Jan 8, 2022
4fc7f38
Integrate DocumentationProviderFeatures in SpringCodegen
cachescrubber Jan 8, 2022
7d11e76
Run new test config spring-boot-springdoc
cachescrubber Jan 8, 2022
a0d6aac
Do not use Locale.ROOT
cachescrubber Jan 8, 2022
e9fc691
Do not use Locale.ROOT, use NONE instead of empty list
cachescrubber Jan 8, 2022
55679cc
Revert "Do not use Locale.ROOT"
cachescrubber Jan 8, 2022
511afee
Do not use forbidden APIs
cachescrubber Jan 8, 2022
e9c5f7d
Fix spring maven plugin example
cachescrubber Jan 8, 2022
b7160a1
Introduce DocumentationProviderFeaturesTest.java
cachescrubber Jan 8, 2022
75a722c
replace AUTO with preferredAnnotationLibrary
cachescrubber Jan 9, 2022
4aaec1d
remove sout.println from Test
cachescrubber Jan 9, 2022
6545e41
Apply code style.
cachescrubber Jan 10, 2022
ace2182
Merge branch 'master' into feature/documentation_provider_pr
cachescrubber Jan 17, 2022
fa103a5
Update spring sample configuration to use the new property
cachescrubber Jan 17, 2022
508665b
Update samples after merge
cachescrubber Jan 17, 2022
cb2e80c
fix atBean import
cachescrubber Jan 17, 2022
b998d34
Generate all samples
cachescrubber Jan 17, 2022
f1e6108
Add ParameterObject to test
cachescrubber Jan 17, 2022
649843a
Allow Subclasses to opt out
cachescrubber Jan 17, 2022
34411e8
Use OpenAPI 2 (fka Swagger RESTful API Documentation Specification) i…
cachescrubber Jan 19, 2022
71c80b0
export generator docs
cachescrubber Jan 19, 2022
c627c09
Fix typo
cachescrubber Jan 19, 2022
f171ace
Fix typo - update docs.
cachescrubber Jan 20, 2022
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
10 changes: 10 additions & 0 deletions bin/configs/spring-boot-springdoc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
generatorName: spring
outputDir: samples/openapi3/server/petstore/spring-boot-springdoc
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/JavaSpring
additionalProperties:
documentationProvider: springdoc
groupId: org.openapitools.openapi3
artifactId: spring-boot-springdoc
snapshotVersion: "true"
hideGenerationTimestamp: "true"
1 change: 1 addition & 0 deletions modules/openapi-generator-maven-plugin/examples/spring.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

<!-- pass any necessary config options -->
<configOptions>
<documentationProvider>springfox</documentationProvider>
<serializableModel>true</serializableModel>
<snapshotVersion>true</snapshotVersion>
</configOptions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.languages.features.DocumentationProviderFeatures;
import org.openapitools.codegen.meta.features.*;
import org.openapitools.codegen.utils.ModelUtils;
import org.slf4j.Logger;
Expand All @@ -48,7 +49,8 @@

import static org.openapitools.codegen.utils.StringUtils.*;

public abstract class AbstractJavaCodegen extends DefaultCodegen implements CodegenConfig {
public abstract class AbstractJavaCodegen extends DefaultCodegen implements CodegenConfig,
DocumentationProviderFeatures {

private final Logger LOGGER = LoggerFactory.getLogger(AbstractJavaCodegen.class);
private static final String ARTIFACT_VERSION_DEFAULT_VALUE = "1.0.0";
Expand Down Expand Up @@ -111,6 +113,8 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
protected List<String> additionalModelTypeAnnotations = new LinkedList<>();
protected List<String> additionalEnumTypeAnnotations = new LinkedList<>();
protected boolean openApiNullable = true;
protected DocumentationProvider documentationProvider;
protected AnnotationLibrary annotationLibrary;

public AbstractJavaCodegen() {
super();
Expand Down Expand Up @@ -259,12 +263,60 @@ public AbstractJavaCodegen() {
snapShotVersion.setEnum(snapShotVersionOptions);
cliOptions.add(snapShotVersion);

CliOption documentationProviderCliOption = new CliOption(DOCUMENTATION_PROVIDER,
"Select the OpenAPI documentation provider.")
.defaultValue(defaultDocumentationProvider().toCliOptValue());
supportedDocumentationProvider().forEach(dp ->
documentationProviderCliOption.addEnum(dp.toCliOptValue(), dp.getDescription()));
cliOptions.add(documentationProviderCliOption);

CliOption annotationLibraryCliOption = new CliOption(ANNOTATION_LIBRARY,
"Select the complementary documentation annotation library.")
.defaultValue(defaultDocumentationProvider().getPreferredAnnotationLibrary().toCliOptValue());
supportedAnnotationLibraries().forEach(al ->
annotationLibraryCliOption.addEnum(al.toCliOptValue(), al.getDescription()));
cliOptions.add(annotationLibraryCliOption);
}

@Override
public void processOpts() {
super.processOpts();

documentationProvider = DocumentationProvider.ofCliOption(
(String)additionalProperties.getOrDefault(DOCUMENTATION_PROVIDER,
defaultDocumentationProvider().toCliOptValue())
);

if (! supportedDocumentationProvider().contains(documentationProvider)) {
String msg = String.format(Locale.ROOT,
"The [%s] Documentation Provider is not supported by this generator",
documentationProvider.toCliOptValue());
throw new IllegalArgumentException(msg);
}

annotationLibrary = AnnotationLibrary.ofCliOption(
(String) additionalProperties.getOrDefault(ANNOTATION_LIBRARY,
documentationProvider.getPreferredAnnotationLibrary().toCliOptValue())
);

if (! supportedAnnotationLibraries().contains(annotationLibrary)) {
String msg = String.format(Locale.ROOT, "The Annotation Library [%s] is not supported by this generator",
annotationLibrary.toCliOptValue());
throw new IllegalArgumentException(msg);
}

if (! documentationProvider.supportedAnnotationLibraries().contains(annotationLibrary)) {
String msg = String.format(Locale.ROOT,
"The [%s] documentation provider does not support [%s] as complementary annotation library",
documentationProvider.toCliOptValue(), annotationLibrary.toCliOptValue());
throw new IllegalArgumentException(msg);
}

additionalProperties.put(DOCUMENTATION_PROVIDER, documentationProvider.toCliOptValue());
additionalProperties.put(documentationProvider.getPropertyName(), true);
additionalProperties.put(ANNOTATION_LIBRARY, annotationLibrary.toCliOptValue());
additionalProperties.put(annotationLibrary.getPropertyName(), true);

if (StringUtils.isEmpty(System.getenv("JAVA_POST_PROCESS_FILE"))) {
LOGGER.info("Environment variable JAVA_POST_PROCESS_FILE not defined so the Java code may not be properly formatted. To define it, try 'export JAVA_POST_PROCESS_FILE=\"/usr/local/bin/clang-format -i\"' (Linux/Mac)");
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
Expand Down Expand Up @@ -1759,6 +1811,26 @@ public void setOpenApiNullable(final boolean openApiNullable) {
this.openApiNullable = openApiNullable;
}

@Override
public DocumentationProvider getDocumentationProvider() {
return documentationProvider;
}

@Override
public void setDocumentationProvider(DocumentationProvider documentationProvider) {
this.documentationProvider = documentationProvider;
}

@Override
public AnnotationLibrary getAnnotationLibrary() {
return annotationLibrary;
}

@Override
public void setAnnotationLibrary(AnnotationLibrary annotationLibrary) {
this.annotationLibrary = annotationLibrary;
}

@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
Expand Down Expand Up @@ -1939,4 +2011,5 @@ protected void addAdditionPropertiesToCodeGenModel(CodegenModel codegenModel, Sc
addImport(codegenModel, codegenModel.additionalPropertiesType);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import java.util.Map;
import java.util.regex.Matcher;
import java.util.stream.Collectors;

import org.apache.commons.lang3.tuple.Pair;
import org.openapitools.codegen.CliOption;
import org.openapitools.codegen.CodegenConstants;
Expand Down Expand Up @@ -90,7 +89,6 @@ public class SpringCodegen extends AbstractJavaCodegen
public static final String IMPLICIT_HEADERS = "implicitHeaders";
public static final String OPENAPI_DOCKET_CONFIG = "swaggerDocketConfig";
public static final String API_FIRST = "apiFirst";
public static final String OAS3 = "oas3";
public static final String SPRING_CONTROLLER = "useSpringController";
public static final String HATEOAS = "hateoas";
public static final String RETURN_SUCCESS_CODE = "returnSuccessCode";
Expand Down Expand Up @@ -123,7 +121,6 @@ public class SpringCodegen extends AbstractJavaCodegen
protected boolean returnSuccessCode = false;
protected boolean unhandledException = false;
protected boolean useSpringController = false;
protected boolean oas3 = false;

public SpringCodegen() {
super();
Expand Down Expand Up @@ -199,7 +196,6 @@ public SpringCodegen() {
CliOption.newBoolean(HATEOAS, "Use Spring HATEOAS library to allow adding HATEOAS links", hateoas));
cliOptions
.add(CliOption.newBoolean(RETURN_SUCCESS_CODE, "Generated server returns 2xx code", returnSuccessCode));
cliOptions.add(CliOption.newBoolean(OAS3, "Use OAS 3 Swagger annotations instead of OAS 2 annotations", oas3));
cliOptions.add(CliOption.newBoolean(SPRING_CONTROLLER, "Annotate the generated API as a Spring Controller", useSpringController));
cliOptions.add(CliOption.newBoolean(UNHANDLED_EXCEPTION_HANDLING,
"Declare operation methods to throw a generic exception and allow unhandled exceptions (useful for Spring `@ControllerAdvice` directives).",
Expand Down Expand Up @@ -240,6 +236,29 @@ public String getHelp() {
return "Generates a Java SpringBoot Server application using the SpringFox integration.";
}

@Override
public DocumentationProvider defaultDocumentationProvider() {
return DocumentationProvider.SPRINGDOC;
}

public List<DocumentationProvider> supportedDocumentationProvider() {
List<DocumentationProvider> supportedProviders = new ArrayList<>();
supportedProviders.add(DocumentationProvider.NONE);
supportedProviders.add(DocumentationProvider.SOURCE);
supportedProviders.add(DocumentationProvider.SPRINGFOX);
supportedProviders.add(DocumentationProvider.SPRINGDOC);
return supportedProviders;
}

@Override
public List<AnnotationLibrary> supportedAnnotationLibraries() {
List<AnnotationLibrary> supportedLibraries = new ArrayList<>();
supportedLibraries.add(AnnotationLibrary.NONE);
supportedLibraries.add(AnnotationLibrary.SWAGGER1);
supportedLibraries.add(AnnotationLibrary.SWAGGER2);
return supportedLibraries;
}

@Override
public void processOpts() {

Expand Down Expand Up @@ -372,11 +391,6 @@ public void processOpts() {
}
writePropertyBack(SPRING_CONTROLLER, useSpringController);

if (additionalProperties.containsKey(OAS3)) {
this.setOas3(convertPropertyToBoolean(OAS3));
}
writePropertyBack(OAS3, oas3);

if (additionalProperties.containsKey(RETURN_SUCCESS_CODE)) {
this.setReturnSuccessCode(Boolean.parseBoolean(additionalProperties.get(RETURN_SUCCESS_CODE).toString()));
}
Expand Down Expand Up @@ -513,15 +527,6 @@ public void processOpts() {
additionalProperties.put(RESPONSE_WRAPPER, "Callable");
}

// Springfox cannot be used with oas3 or apiFirst or reactive. So, write the property back after determining
// whether it should be enabled or not.
boolean useSpringFox = false;
if (!apiFirst && !reactive && !oas3) {
useSpringFox = true;
additionalProperties.put("useSpringfox", true);
}
writePropertyBack("useSpringfox", useSpringFox);

// Some well-known Spring or Spring-Cloud response wrappers
if (isNotEmpty(responseWrapper)) {
additionalProperties.put("jdk8", false);
Expand Down Expand Up @@ -880,10 +885,6 @@ public void setUseSpringController(boolean useSpringController) {
this.useSpringController = useSpringController;
}

public void setOas3(boolean oas3) {
this.oas3 = oas3;
}

public void setReturnSuccessCode(boolean returnSuccessCode) {
this.returnSuccessCode = returnSuccessCode;
}
Expand Down Expand Up @@ -927,8 +928,8 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
@Override
public CodegenModel fromModel(String name, Schema model) {
CodegenModel codegenModel = super.fromModel(name, model);
if (oas3) {
// remove swagger2 imports
if (getAnnotationLibrary() != AnnotationLibrary.SWAGGER1) {
// remove swagger imports
codegenModel.imports.remove("ApiModelProperty");
codegenModel.imports.remove("ApiModel");
}
Expand Down
Loading