Skip to content

Commit 7106439

Browse files
refactor: decouple schema naming from discriminator mapping introspection
1 parent 8fa3cb6 commit 7106439

2 files changed

Lines changed: 59 additions & 33 deletions

File tree

modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3404,36 +3404,16 @@ protected List<MappedModel> getOneOfAnyOfDescendants(String composedSchemaName,
34043404
CodegenProperty df = DiscriminatorUtils.discriminatorFound(openAPI, composedSchemaName, sc, discPropName, new TreeSet<String>());
34053405
String modelName = ModelUtils.getSimpleRef(ref);
34063406
if (df == null || !df.isString || !df.required) {
3407-
String msgSuffix = "";
3408-
if (df == null) {
3409-
msgSuffix += discPropName + " is missing from the schema, define it as required and type string";
3410-
} else {
3411-
if (!df.isString) {
3412-
msgSuffix += "invalid type for " + discPropName + ", set it to string";
3413-
}
3414-
if (!df.required) {
3415-
String spacer = "";
3416-
if (msgSuffix.length() != 0) {
3417-
spacer = ". ";
3418-
}
3419-
msgSuffix += spacer + "invalid optional definition of " + discPropName + ", include it in required";
3420-
}
3421-
}
3422-
once(LOGGER).warn("'{}' defines discriminator '{}', but the referenced schema '{}' is incorrect. {}",
3423-
composedSchemaName, discPropName, modelName, msgSuffix);
3407+
once(LOGGER).warn(getDiscriminatorSchemaError(df, discPropName, modelName, composedSchemaName));
34243408
}
3425-
MappedModel mm = new MappedModel(modelName, toModelName(modelName), modelName, false);
3409+
MappedModel mm = new MappedModel(modelName, modelName, modelName, false);
34263410
descendentSchemas.add(mm);
34273411
Schema cs = ModelUtils.getSchema(openAPI, modelName);
34283412
if (cs == null) { // cannot lookup the model based on the name
34293413
once(LOGGER).error("Failed to lookup the schema '{}' when processing oneOf/anyOf. Please check to ensure it's defined properly.", modelName);
34303414
} else {
3431-
Map<String, Object> vendorExtensions = cs.getExtensions();
3432-
if (vendorExtensions != null && !vendorExtensions.isEmpty() && vendorExtensions.containsKey(X_DISCRIMINATOR_VALUE)) {
3433-
String xDiscriminatorValue = (String) vendorExtensions.get(X_DISCRIMINATOR_VALUE);
3434-
mm = new MappedModel(xDiscriminatorValue, toModelName(modelName), modelName, true);
3435-
descendentSchemas.add(mm);
3436-
}
3415+
discriminatorVendorExtensionValue(cs)
3416+
.ifPresent(discriminatorValue -> descendentSchemas.add(new MappedModel(discriminatorValue, modelName, modelName, true)));
34373417
}
34383418
}
34393419
}
@@ -3483,13 +3463,9 @@ protected List<MappedModel> getAllOfDescendants(String thisSchemaName) {
34833463
}
34843464
currentSchemaName = queue.remove(0);
34853465
Schema cs = schemas.get(currentSchemaName);
3486-
Map<String, Object> vendorExtensions = cs.getExtensions();
3487-
String mappingName =
3488-
Optional.ofNullable(vendorExtensions)
3489-
.map(ve -> ve.get(X_DISCRIMINATOR_VALUE))
3490-
.map(discriminatorValue -> (String) discriminatorValue)
3466+
String mappingName = discriminatorVendorExtensionValue(cs)
34913467
.orElse(currentSchemaName);
3492-
MappedModel mm = new MappedModel(mappingName, toModelName(currentSchemaName), currentSchemaName, !mappingName.equals(currentSchemaName));
3468+
MappedModel mm = new MappedModel(mappingName, currentSchemaName, currentSchemaName, !mappingName.equals(currentSchemaName));
34933469
descendentSchemas.add(mm);
34943470
}
34953471
return descendentSchemas;
@@ -3560,7 +3536,8 @@ protected CodegenDiscriminator createDiscriminator(String schemaName, Schema sch
35603536
boolean legacyUseCase = (this.getLegacyDiscriminatorBehavior() && uniqueDescendants.isEmpty());
35613537
if (!this.getLegacyDiscriminatorBehavior() || legacyUseCase) {
35623538
// for schemas that allOf inherit from this schema, add those descendants to this discriminator map
3563-
List<MappedModel> otherDescendants = getAllOfDescendants(schemaName);
3539+
List<MappedModel> otherDescendants =
3540+
adjustModelNames(getAllOfDescendants(schemaName));
35643541
for (MappedModel otherDescendant : otherDescendants) {
35653542
// add only if the mapping names are not the same and the model names are not the same
35663543
boolean matched = false;
@@ -3579,7 +3556,8 @@ protected CodegenDiscriminator createDiscriminator(String schemaName, Schema sch
35793556
}
35803557
// if there are composed oneOf/anyOf schemas, add them to this discriminator
35813558
if (ModelUtils.isComposedSchema(schema) && !this.getLegacyDiscriminatorBehavior()) {
3582-
List<MappedModel> otherDescendants = getOneOfAnyOfDescendants(schemaName, discriminatorPropertyName, schema);
3559+
List<MappedModel> otherDescendants =
3560+
adjustModelNames(getOneOfAnyOfDescendants(schemaName, discriminatorPropertyName, schema));
35833561
for (MappedModel otherDescendant : otherDescendants) {
35843562
// add only if the model names are not the same
35853563
if (uniqueDescendants.stream().map(MappedModel::getModelName).noneMatch(it -> it.equals(otherDescendant.getModelName()))) {
@@ -8820,4 +8798,16 @@ protected void handleConstantParams(CodegenOperation operation) {
88208798
}
88218799
}
88228800
}
8801+
8802+
/**
8803+
* Adjust the model name of the list of {@link MappedModel} to ensure that the names are consistent with the
8804+
* language specific model name expressed in the {@link CodegenConfig#toModelName(String)} method.
8805+
* @param mappedModels The {@link MappedModel}
8806+
* @return The {@link MappedModel} with the modelName adjusted to the language specific model name.
8807+
*/
8808+
private List<MappedModel> adjustModelNames(List<MappedModel> mappedModels) {
8809+
return mappedModels.stream()
8810+
.peek(mappedModel -> mappedModel.setModelName(toModelName(mappedModel.getSchemaName())))
8811+
.collect(Collectors.toList());
8812+
}
88238813
}

modules/openapi-generator/src/main/java/org/openapitools/codegen/utils/DiscriminatorUtils.java

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,11 @@
77
import org.openapitools.codegen.CodegenProperty;
88
import org.slf4j.Logger;
99
import org.slf4j.LoggerFactory;
10+
import org.slf4j.helpers.MessageFormatter;
1011

1112
import java.util.*;
1213

14+
import static org.openapitools.codegen.CodegenConstants.X_DISCRIMINATOR_VALUE;
1315
import static org.openapitools.codegen.utils.OnceLogger.once;
1416

1517
public class DiscriminatorUtils {
@@ -24,7 +26,8 @@ public class DiscriminatorUtils {
2426
"'{}' defines discriminator '{}', but the referenced schema '{}' is missing {}";
2527
private static final String DEFINES_DISCRIMINATOR_BUT_ALTERNATIVE_HAS_OTHER_DEFINITION =
2628
"'{}' defines discriminator '{}', but the schema '{}' has a different {} definition than the prior schema's. Make sure the {} type and required values are the same";
27-
29+
private static final String DEFINES_DISCRIMINATOR_BUT_REFERENCE_IS_INCORRECT =
30+
"'{}' defines discriminator '{}', but the referenced schema '{}' is incorrect. {}";
2831
/**
2932
* Recursively look in Schema sc for the discriminator discPropName
3033
* and return a CodegenProperty with the dataType and required params set
@@ -180,6 +183,39 @@ public static DiscriminatorData recursiveGetDiscriminator(
180183
return null;
181184
}
182185

186+
/**
187+
* Get the value of the vendor extension {@code x-discriminator-value} from the schema, if present.
188+
* @param schema the schema to check for the vendor extension
189+
* @return the value of the vendor extension, or an empty optional if not present
190+
*/
191+
public static Optional<String> discriminatorVendorExtensionValue(Schema schema) {
192+
return Optional.ofNullable(schema)
193+
.map(Schema::getExtensions)
194+
.map(vendorExtensions -> vendorExtensions.get(X_DISCRIMINATOR_VALUE))
195+
.map(discriminatorValue -> (String) discriminatorValue);
196+
}
197+
198+
public static String getDiscriminatorSchemaError(CodegenProperty codegenProperty, String discPropName,
199+
String modelName, String composedSchemaName) {
200+
String msgSuffix = "";
201+
if (codegenProperty == null) {
202+
msgSuffix += discPropName + " is missing from the schema, define it as required and type string";
203+
} else {
204+
if (!codegenProperty.isString) {
205+
msgSuffix += "invalid type for " + discPropName + ", set it to string";
206+
}
207+
if (!codegenProperty.required) {
208+
String spacer = "";
209+
if (!msgSuffix.isEmpty()) {
210+
spacer = ". ";
211+
}
212+
msgSuffix += spacer + "invalid optional definition of " + discPropName + ", include it in required";
213+
}
214+
}
215+
return MessageFormatter.arrayFormat(DEFINES_DISCRIMINATOR_BUT_REFERENCE_IS_INCORRECT,
216+
new Object[]{composedSchemaName, discPropName, modelName, msgSuffix}).getMessage();
217+
}
218+
183219
/**
184220
* Get the Schema for the discriminator type. Requires special handling due to siblings from OAS 3.1.
185221
* An example of a sibling is an enum-ref that has its own description. This will lead to the enum being

0 commit comments

Comments
 (0)