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

Support openApiNullable in jaxrs-cxf-client generator #8863

Merged
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
generatorName: jaxrs-cxf-client
outputDir: samples/openapi3/client/petstore/jaxrs-cxf-client-jackson-nullable
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
templateDir: modules/openapi-generator/src/main/resources/JavaJaxRS/cxf
additionalProperties:
jackson: "true"
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
public static final String ADDITIONAL_ENUM_TYPE_ANNOTATIONS = "additionalEnumTypeAnnotations";
public static final String DISCRIMINATOR_CASE_SENSITIVE = "discriminatorCaseSensitive";
public static final String OPENAPI_NULLABLE = "openApiNullable";
public static final String JACKSON = "jackson";

protected String dateLibrary = "threetenbp";
protected boolean supportAsync = false;
Expand Down Expand Up @@ -524,6 +525,7 @@ public void processOpts() {
importMapping.put("JsonValue", "com.fasterxml.jackson.annotation.JsonValue");
importMapping.put("JsonIgnore", "com.fasterxml.jackson.annotation.JsonIgnore");
importMapping.put("JsonInclude", "com.fasterxml.jackson.annotation.JsonInclude");
importMapping.put("JsonNullable", "org.openapitools.jackson.nullable.JsonNullable");
importMapping.put("SerializedName", "com.google.gson.annotations.SerializedName");
importMapping.put("TypeAdapter", "com.google.gson.TypeAdapter");
importMapping.put("JsonAdapter", "com.google.gson.annotations.JsonAdapter");
Expand Down Expand Up @@ -1177,7 +1179,7 @@ public CodegenModel fromModel(String name, Schema model) {
if (codegenModel.description != null) {
codegenModel.imports.add("ApiModel");
}
if (codegenModel.discriminator != null && additionalProperties.containsKey("jackson")) {
if (codegenModel.discriminator != null && additionalProperties.containsKey(JACKSON)) {
codegenModel.imports.add("JsonSubTypes");
codegenModel.imports.add("JsonTypeInfo");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public AbstractJavaJAXRSServerCodegen() {

additionalProperties.put("title", title);
// java inflector uses the jackson lib
additionalProperties.put("jackson", "true");
additionalProperties.put(JACKSON, "true");

cliOptions.add(new CliOption(CodegenConstants.IMPL_FOLDER, CodegenConstants.IMPL_FOLDER_DESC).defaultValue(implFolder));
cliOptions.add(new CliOption("title", "a title describing the application").defaultValue(title));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public class JavaCXFClientCodegen extends AbstractJavaCodegen

protected boolean useLoggingFeatureForTests = false;

private boolean useJackson = false;

public JavaCXFClientCodegen() {
super();

Expand Down Expand Up @@ -108,6 +110,10 @@ public void processOpts() {
this.setUseLoggingFeatureForTests(convertPropertyToBooleanAndWriteBack(USE_LOGGING_FEATURE_FOR_TESTS));
}

if (additionalProperties.containsKey(JACKSON)) {
useJackson = convertPropertyToBooleanAndWriteBack(JACKSON);
}

supportingFiles.clear(); // Don't need extra files provided by AbstractJAX-RS & Java Codegen

supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml")
Expand Down Expand Up @@ -139,12 +145,22 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
model.imports.remove("JsonSerialize");
model.imports.remove("ToStringSerializer");

//Add imports for Jackson when model has inner enum
if (additionalProperties.containsKey("jackson")) {

if (useJackson) {
//Add jackson imports when model has inner enum
if (Boolean.FALSE.equals(model.isEnum) && Boolean.TRUE.equals(model.hasEnums)) {
model.imports.add("JsonCreator");
model.imports.add("JsonValue");
}

//Add JsonNullable import and mark property nullable for templating if necessary
if (openApiNullable) {
if (Boolean.FALSE.equals(property.required) && Boolean.TRUE.equals(property.isNullable)) {
property.getVendorExtensions().put("x-is-jackson-optional-nullable", true);
model.imports.add("JsonNullable");
model.imports.add("JsonIgnore");
}
}
}
}

Expand Down Expand Up @@ -195,4 +211,7 @@ public boolean isUseGenericResponse() {
return useGenericResponse;
}

public boolean isUseJackson() {
return useJackson;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
model.imports.remove("ToStringSerializer");

//Add imports for Jackson when model has inner enum
if (additionalProperties.containsKey("jackson")) {
if (additionalProperties.containsKey(JACKSON)) {
if (Boolean.FALSE.equals(model.isEnum) && Boolean.TRUE.equals(model.hasEnums)) {
model.imports.add("JsonCreator");
model.imports.add("JsonValue");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public JavaInflectorServerCodegen() {

additionalProperties.put("title", title);
// java inflector uses the jackson lib
additionalProperties.put("jackson", "true");
additionalProperties.put(JACKSON, "true");
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public class JavaJAXRSSpecServerCodegen extends AbstractJavaJAXRSServerCodegen {
public static final String RETURN_RESPONSE = "returnResponse";
public static final String GENERATE_POM = "generatePom";
public static final String USE_SWAGGER_ANNOTATIONS = "useSwaggerAnnotations";
public static final String JACKSON = "jackson";
public static final String OPEN_API_SPEC_FILE_LOCATION = "openApiSpecFileLocation";
public static final String GENERATE_BUILDERS = "generateBuilders";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public JavaPKMSTServerCodegen() {
updateOption(CodegenConstants.API_PACKAGE, apiPackage);
updateOption(CodegenConstants.MODEL_PACKAGE, modelPackage);

additionalProperties.put("jackson", "true");
additionalProperties.put(JACKSON, "true");

this.cliOptions.add(new CliOption("basePackage", "base package for java source code"));
this.cliOptions.add(new CliOption("serviceName", "Service Name"));
Expand Down Expand Up @@ -422,7 +422,7 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
}
} else { // enum class
// Needed imports for Jackson's JsonCreator
if (this.additionalProperties.containsKey("jackson")) {
if (this.additionalProperties.containsKey(JACKSON)) {
model.imports.add("JsonCreator");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public JavaPlayFrameworkCodegen() {
updateOption(CodegenConstants.MODEL_PACKAGE, modelPackage);

additionalProperties.put("java8", true);
additionalProperties.put("jackson", "true");
additionalProperties.put(JACKSON, "true");

cliOptions.add(new CliOption(TITLE, "server title name or client service name").defaultValue(title));
cliOptions.add(new CliOption(CONFIG_PACKAGE, "configuration package for generated code").defaultValue(getConfigPackage()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public SpringCodegen() {
apiTestTemplateFiles.clear(); // TODO: add test template

// spring uses the jackson lib
additionalProperties.put("jackson", "true");
additionalProperties.put(JACKSON, "true");
additionalProperties.put("openbrace", OPEN_BRACE);
additionalProperties.put("closebrace", CLOSE_BRACE);

Expand Down Expand Up @@ -829,7 +829,7 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
}
} else { // enum class
//Needed imports for Jackson's JsonCreator
if (additionalProperties.containsKey("jackson")) {
if (additionalProperties.containsKey(JACKSON)) {
model.imports.add("JsonCreator");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,23 @@ import com.fasterxml.jackson.annotation.JsonProperty;
* {{{description}}}
**/
{{/description}}
{{#isContainer}}
{{#vendorExtensions.x-is-jackson-optional-nullable}}
{{#isContainer}}
private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>undefined();
{{/isContainer}}
{{^isContainer}}
private JsonNullable<{{{datatypeWithEnum}}}> {{name}} = JsonNullable.<{{{datatypeWithEnum}}}>{{#defaultValue}}of({{{.}}}){{/defaultValue}}{{^defaultValue}}undefined(){{/defaultValue}};
{{/isContainer}}
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
{{#isContainer}}
private {{{datatypeWithEnum}}} {{name}}{{#required}} = {{{defaultValue}}}{{/required}}{{^required}} = null{{/required}};
{{/isContainer}}
{{^isContainer}}
{{/isContainer}}
{{^isContainer}}
private {{{datatypeWithEnum}}} {{name}}{{#defaultValue}} = {{{.}}}{{/defaultValue}};
{{/isContainer}}
{{/vars}}
{{/isContainer}}
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{/vars}}
{{#vars}}
/**
{{#description}}
Expand All @@ -51,44 +61,115 @@ import com.fasterxml.jackson.annotation.JsonProperty;
{{/maximum}}
* @return {{name}}
**/
@JsonProperty("{{baseName}}")
{{#vendorExtensions.x-extra-annotation}}
{{{vendorExtensions.x-extra-annotation}}}
{{/vendorExtensions.x-extra-annotation}}
{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#isEnum}}{{^isArray}}{{^isMap}}public {{dataType}} {{getter}}() {
{{#vendorExtensions.x-is-jackson-optional-nullable}}
{{!unannotated, Jackson would pick this up automatically and add it *in addition* to the _JsonNullable getter field}}
@JsonIgnore
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
@JsonProperty("{{baseName}}")
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{#useBeanValidation}}{{>beanValidation}}{{/useBeanValidation}} {{#isEnum}}{{^isContainer}}public {{dataType}} {{getter}}() {
{{#vendorExtensions.x-is-jackson-optional-nullable}}
if ({{name}} == null || !{{name}}.isPresent() || {{name}}.get() == null) {
return null;
}
return {{name}}.get().value();
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
if ({{name}} == null) {
return null;
}
return {{name}}.value();
}{{/isMap}}{{/isArray}}{{/isEnum}}{{#isEnum}}{{#isArray}}public {{{datatypeWithEnum}}} {{getter}}() {
return {{name}};
}{{/isArray}}{{/isEnum}}{{#isEnum}}{{#isMap}}public {{{datatypeWithEnum}}} {{getter}}() {
{{/vendorExtensions.x-is-jackson-optional-nullable}}
}{{/isContainer}}{{#isContainer}}public {{{datatypeWithEnum}}} {{getter}}() {
{{#vendorExtensions.x-is-jackson-optional-nullable}}
if ({{name}} == null) {
return null;
}
return {{name}}.orElse(null);
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
return {{name}};
}{{/isMap}}{{/isEnum}}{{^isEnum}}public {{{datatypeWithEnum}}} {{getter}}() {
{{/vendorExtensions.x-is-jackson-optional-nullable}}
}{{/isContainer}}{{/isEnum}}{{^isEnum}}public {{{datatypeWithEnum}}} {{getter}}() {
{{#vendorExtensions.x-is-jackson-optional-nullable}}
if ({{name}} == null) {
return null;
}
return {{name}}.orElse(null);
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
return {{name}};
{{/vendorExtensions.x-is-jackson-optional-nullable}}
}{{/isEnum}}
{{#vendorExtensions.x-is-jackson-optional-nullable}}

@JsonProperty("{{baseName}}")
public JsonNullable<{{{datatypeWithEnum}}}> {{getter}}_JsonNullable() {
return {{name}};
}
{{/vendorExtensions.x-is-jackson-optional-nullable}}

{{^isReadOnly}}
public void {{setter}}({{{datatypeWithEnum}}} {{name}}) {
{{#vendorExtensions.x-is-jackson-optional-nullable}}
this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
this.{{name}} = {{name}};
{{/vendorExtensions.x-is-jackson-optional-nullable}}
}
{{#vendorExtensions.x-is-jackson-optional-nullable}}

@JsonProperty("{{baseName}}")
public void {{setter}}_JsonNullable(JsonNullable<{{{datatypeWithEnum}}}> {{name}}) {
{{! For getters/setters that have name differing from attribute name, we must include setter (albeit private) for jackson to be able to set the attribute}}
this.{{name}} = {{name}};
}
{{/vendorExtensions.x-is-jackson-optional-nullable}}

public {{classname}} {{name}}({{{datatypeWithEnum}}} {{name}}) {
{{#vendorExtensions.x-is-jackson-optional-nullable}}
this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{name}});
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
this.{{name}} = {{name}};
{{/vendorExtensions.x-is-jackson-optional-nullable}}
return this;
}
{{#isArray}}

public {{classname}} add{{nameInCamelCase}}Item({{{items.datatypeWithEnum}}} {{name}}Item) {
{{#vendorExtensions.x-is-jackson-optional-nullable}}
if (this.{{name}} == null || !this.{{name}}.isPresent()) {
this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}});
}
this.{{name}}.get().add({{name}}Item);
return this;
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
this.{{name}}.add({{name}}Item);
return this;
{{/vendorExtensions.x-is-jackson-optional-nullable}}
}
{{/isArray}}
{{#isMap}}

public {{classname}} put{{nameInCamelCase}}Item(String key, {{{items.datatypeWithEnum}}} {{name}}Item) {
{{#vendorExtensions.x-is-jackson-optional-nullable}}
if (this.{{name}} == null || !this.{{name}}.isPresent()) {
this.{{name}} = JsonNullable.<{{{datatypeWithEnum}}}>of({{{defaultValue}}});
}
this.{{name}}.get().put(key, {{name}}Item);
return this;
{{/vendorExtensions.x-is-jackson-optional-nullable}}
{{^vendorExtensions.x-is-jackson-optional-nullable}}
this.{{name}}.put(key, {{name}}Item);
return this;
{{/vendorExtensions.x-is-jackson-optional-nullable}}
}
{{/isMap}}
{{/isReadOnly}}
Expand Down
Loading