Centralize the definition of vendor extensions tied to the discriminator (#22542)

This commit is contained in:
Mattias Sehlstedt
2025-12-17 07:59:18 +01:00
committed by GitHub
parent a9f439f1c6
commit 09a5800771
10 changed files with 43 additions and 30 deletions

View File

@@ -483,4 +483,9 @@ public class CodegenConstants {
public static final String X_MODIFIERS = "x-modifiers";
public static final String X_MODIFIER_PREFIX = "x-modifier-";
public static final String X_MODEL_IS_MUTABLE = "x-model-is-mutable";
public static final String X_IMPLEMENTS = "x-implements";
public static final String X_IS_ONE_OF_INTERFACE = "x-is-one-of-interface";
public static final String X_DISCRIMINATOR_VALUE = "x-discriminator-value";
public static final String X_ONE_OF_NAME = "x-one-of-name";
public static final String X_NULLABLE = "x-nullable";
}

View File

@@ -527,7 +527,7 @@ public class DefaultCodegen implements CodegenConfig {
for (ModelMap mo : modelsAttrs.getModels()) {
CodegenModel cm = mo.getModel();
if (cm.oneOf.size() > 0) {
cm.vendorExtensions.put("x-is-one-of-interface", true);
cm.vendorExtensions.put(X_IS_ONE_OF_INTERFACE, true);
for (String one : cm.oneOf) {
if (!additionalDataMap.containsKey(one)) {
additionalDataMap.put(one, new OneOfImplementorAdditionalData(one));
@@ -2348,8 +2348,8 @@ public class DefaultCodegen implements CodegenConfig {
@SuppressWarnings("static-method")
public String toOneOfName(List<String> names, Schema composedSchema) {
Map<String, Object> exts = composedSchema.getExtensions();
if (exts != null && exts.containsKey("x-one-of-name")) {
return (String) exts.get("x-one-of-name");
if (exts != null && exts.containsKey(X_ONE_OF_NAME)) {
return (String) exts.get(X_ONE_OF_NAME);
}
return "oneOf<" + String.join(",", names) + ">";
}
@@ -3548,8 +3548,8 @@ public class DefaultCodegen implements CodegenConfig {
once(LOGGER).error("Failed to lookup the schema '{}' when processing oneOf/anyOf. Please check to ensure it's defined properly.", modelName);
} else {
Map<String, Object> vendorExtensions = cs.getExtensions();
if (vendorExtensions != null && !vendorExtensions.isEmpty() && vendorExtensions.containsKey("x-discriminator-value")) {
String xDiscriminatorValue = (String) vendorExtensions.get("x-discriminator-value");
if (vendorExtensions != null && !vendorExtensions.isEmpty() && vendorExtensions.containsKey(X_DISCRIMINATOR_VALUE)) {
String xDiscriminatorValue = (String) vendorExtensions.get(X_DISCRIMINATOR_VALUE);
mm = new MappedModel(xDiscriminatorValue, toModelName(modelName), true);
descendentSchemas.add(mm);
}
@@ -3605,7 +3605,7 @@ public class DefaultCodegen implements CodegenConfig {
Map<String, Object> vendorExtensions = cs.getExtensions();
String mappingName =
Optional.ofNullable(vendorExtensions)
.map(ve -> ve.get("x-discriminator-value"))
.map(ve -> ve.get(X_DISCRIMINATOR_VALUE))
.map(discriminatorValue -> (String) discriminatorValue)
.orElse(currentSchemaName);
MappedModel mm = new MappedModel(mappingName, toModelName(currentSchemaName), !mappingName.equals(currentSchemaName));
@@ -4098,8 +4098,8 @@ public class DefaultCodegen implements CodegenConfig {
if (referencedSchema.getNullable() != null) {
property.isNullable = referencedSchema.getNullable();
} else if (referencedSchema.getExtensions() != null &&
referencedSchema.getExtensions().containsKey("x-nullable")) {
property.isNullable = (Boolean) referencedSchema.getExtensions().get("x-nullable");
referencedSchema.getExtensions().containsKey(X_NULLABLE)) {
property.isNullable = (Boolean) referencedSchema.getExtensions().get(X_NULLABLE);
}
final XML referencedSchemaXml = referencedSchema.getXml();
@@ -4201,8 +4201,8 @@ public class DefaultCodegen implements CodegenConfig {
// evaluate common attributes if defined in the top level
if (p.getNullable() != null) {
property.isNullable = p.getNullable();
} else if (p.getExtensions() != null && p.getExtensions().containsKey("x-nullable")) {
property.isNullable = (Boolean) p.getExtensions().get("x-nullable");
} else if (p.getExtensions() != null && p.getExtensions().containsKey(X_NULLABLE)) {
property.isNullable = (Boolean) p.getExtensions().get(X_NULLABLE);
}
if (p.getReadOnly() != null) {
@@ -8047,8 +8047,8 @@ public class DefaultCodegen implements CodegenConfig {
// evaluate common attributes such as description if defined in the top level
if (original.getNullable() != null) {
codegenParameter.isNullable = original.getNullable();
} else if (original.getExtensions() != null && original.getExtensions().containsKey("x-nullable")) {
codegenParameter.isNullable = (Boolean) original.getExtensions().get("x-nullable");
} else if (original.getExtensions() != null && original.getExtensions().containsKey(X_NULLABLE)) {
codegenParameter.isNullable = (Boolean) original.getExtensions().get(X_NULLABLE);
}
if (original.getExtensions() != null) {
@@ -8464,7 +8464,7 @@ public class DefaultCodegen implements CodegenConfig {
*/
public void addOneOfNameExtension(Schema schema, String name) {
if (schema.getOneOf() != null && schema.getOneOf().size() > 0) {
schema.addExtension("x-one-of-name", name);
schema.addExtension(X_ONE_OF_NAME, name);
}
}
@@ -8498,7 +8498,7 @@ public class DefaultCodegen implements CodegenConfig {
}
cm.name = type;
cm.classname = type;
cm.vendorExtensions.put("x-is-one-of-interface", true);
cm.vendorExtensions.put(X_IS_ONE_OF_INTERFACE, true);
cm.interfaceModels = new ArrayList<>();
addOneOfInterfaces.add(cm);

View File

@@ -37,8 +37,7 @@ import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import static org.openapitools.codegen.CodegenConstants.X_INTERNAL;
import static org.openapitools.codegen.CodegenConstants.X_PARENT;
import static org.openapitools.codegen.CodegenConstants.*;
import static org.openapitools.codegen.utils.ModelUtils.simplifyOneOfAnyOfWithOnlyOneNonNullSubSchema;
import static org.openapitools.codegen.utils.StringUtils.getUniqueString;
@@ -1570,7 +1569,7 @@ public class OpenAPINormalizer {
}
protected Schema setNullable(Schema schema) {
if (schema.getNullable() != null || (schema.getExtensions() != null && schema.getExtensions().containsKey("x-nullable"))) {
if (schema.getNullable() != null || (schema.getExtensions() != null && schema.getExtensions().containsKey(X_NULLABLE))) {
// already set, don't overwrite
return schema;
}

View File

@@ -71,6 +71,7 @@ import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static org.openapitools.codegen.CodegenConstants.X_IMPLEMENTS;
import static org.openapitools.codegen.utils.CamelizeOption.*;
import static org.openapitools.codegen.utils.ModelUtils.getSchemaItems;
import static org.openapitools.codegen.utils.OnceLogger.once;
@@ -1997,8 +1998,8 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
for (ModelMap mo : objs.getModels()) {
CodegenModel cm = mo.getModel();
if (this.serializableModel) {
cm.getVendorExtensions().putIfAbsent("x-implements", new ArrayList<String>());
((ArrayList<String>) cm.getVendorExtensions().get("x-implements")).add("Serializable");
cm.getVendorExtensions().putIfAbsent(X_IMPLEMENTS, new ArrayList<String>());
((ArrayList<String>) cm.getVendorExtensions().get(X_IMPLEMENTS)).add("Serializable");
}
}

View File

@@ -47,6 +47,7 @@ import java.util.regex.Pattern;
import static com.google.common.base.CaseFormat.LOWER_CAMEL;
import static com.google.common.base.CaseFormat.UPPER_UNDERSCORE;
import static java.util.Collections.sort;
import static org.openapitools.codegen.CodegenConstants.X_IMPLEMENTS;
import static org.openapitools.codegen.utils.CamelizeOption.LOWERCASE_FIRST_LETTER;
import static org.openapitools.codegen.utils.StringUtils.camelize;
@@ -1173,7 +1174,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
for (ModelMap mo : models) {
CodegenModel cm = mo.getModel();
cm.getVendorExtensions().putIfAbsent("x-implements", new ArrayList<String>());
cm.getVendorExtensions().putIfAbsent(X_IMPLEMENTS, new ArrayList<String>());
if (isLibrary(JERSEY2) || isLibrary(JERSEY3) || isLibrary(NATIVE) || isLibrary(OKHTTP_GSON)) {
if (cm.oneOf != null && !cm.oneOf.isEmpty() && cm.oneOf.contains("ModelNull")) {
// if oneOf contains "null" type
@@ -1188,7 +1189,7 @@ public class JavaClientCodegen extends AbstractJavaCodegen
}
}
if (this.parcelableModel && !cm.isEnum) {
((ArrayList<String>) cm.getVendorExtensions().get("x-implements")).add("Parcelable");
((ArrayList<String>) cm.getVendorExtensions().get(X_IMPLEMENTS)).add("Parcelable");
}
}

View File

@@ -48,6 +48,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.openapitools.codegen.CodegenConstants.X_ONE_OF_NAME;
import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
@@ -1406,8 +1407,8 @@ public class RustServerCodegen extends AbstractRustCodegen implements CodegenCon
if (composedSchema != null) {
exts = composedSchema.getExtensions();
}
if (exts != null && exts.containsKey("x-one-of-name")) {
return (String) exts.get("x-one-of-name");
if (exts != null && exts.containsKey(X_ONE_OF_NAME)) {
return (String) exts.get(X_ONE_OF_NAME);
}
List<Schema> schemas = ModelUtils.getInterfaces(composedSchema);

View File

@@ -48,6 +48,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.openapitools.codegen.CodegenConstants.X_ONE_OF_NAME;
import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.underscore;
@@ -1386,8 +1387,8 @@ public class RustServerCodegenDeprecated extends AbstractRustCodegen implements
if (composedSchema != null) {
exts = composedSchema.getExtensions();
}
if (exts != null && exts.containsKey("x-one-of-name")) {
return (String) exts.get("x-one-of-name");
if (exts != null && exts.containsKey(X_ONE_OF_NAME)) {
return (String) exts.get(X_ONE_OF_NAME);
}
List<Schema> schemas = ModelUtils.getInterfaces(composedSchema);

View File

@@ -32,6 +32,8 @@ import java.io.File;
import java.util.*;
import java.util.stream.Collectors;
import static org.openapitools.codegen.CodegenConstants.X_IMPLEMENTS;
public class ScalaHttp4sServerCodegen extends DefaultCodegen implements CodegenConfig {
private final Logger LOGGER = LoggerFactory.getLogger(ScalaHttp4sServerCodegen.class);
protected String artifactId = "http4s-server";
@@ -374,7 +376,7 @@ public class ScalaHttp4sServerCodegen extends DefaultCodegen implements CodegenC
}
//
try {
List<String> exts = (List<String>) cModel.getVendorExtensions().get("x-implements");
List<String> exts = (List<String>) cModel.getVendorExtensions().get(X_IMPLEMENTS);
if (exts != null) {
cModel.getVendorExtensions().put("x-extends", exts.subList(0, 1));
cModel.getVendorExtensions().put("x-extendsWith", exts.subList(1, exts.size()));

View File

@@ -56,6 +56,7 @@ import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import static org.openapitools.codegen.CodegenConstants.X_NULLABLE;
import static org.openapitools.codegen.CodegenConstants.X_PARENT;
import static org.openapitools.codegen.utils.OnceLogger.once;
@@ -1757,8 +1758,8 @@ public class ModelUtils {
return true;
}
if (schema.getExtensions() != null && schema.getExtensions().get("x-nullable") != null) {
return Boolean.parseBoolean(schema.getExtensions().get("x-nullable").toString());
if (schema.getExtensions() != null && schema.getExtensions().get(X_NULLABLE) != null) {
return Boolean.parseBoolean(schema.getExtensions().get(X_NULLABLE).toString());
}
// In OAS 3.1, the recommended way to define a nullable property or object is to use oneOf.
if (isComposedSchema(schema)) {

View File

@@ -9,6 +9,8 @@ import org.slf4j.LoggerFactory;
import java.util.*;
import static org.openapitools.codegen.CodegenConstants.X_IMPLEMENTS;
/**
* This class holds data to add to `oneOf` members. Let's consider this example:
* <p>
@@ -101,11 +103,11 @@ public class OneOfImplementorAdditionalData {
*/
@SuppressWarnings("unchecked")
public void addToImplementor(CodegenConfig cc, CodegenModel implcm, List<Map<String, String>> implImports, boolean addInterfaceImports) {
implcm.getVendorExtensions().putIfAbsent("x-implements", new ArrayList<String>());
implcm.getVendorExtensions().putIfAbsent(X_IMPLEMENTS, new ArrayList<String>());
// Add implemented interfaces
for (String intf : additionalInterfaces) {
List<String> impl = (List<String>) implcm.getVendorExtensions().get("x-implements");
List<String> impl = (List<String>) implcm.getVendorExtensions().get(X_IMPLEMENTS);
impl.add(intf);
if (addInterfaceImports) {
// Add imports for interfaces