Skip to content

Commit 5ba7970

Browse files
refactor: add a schema utils class with common schema operations
1 parent 3971b4f commit 5ba7970

12 files changed

Lines changed: 103 additions & 61 deletions

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import org.openapitools.codegen.utils.ExamplesUtils;
7070
import org.openapitools.codegen.utils.ModelUtils;
7171
import org.openapitools.codegen.utils.OneOfImplementorAdditionalData;
72+
import org.openapitools.codegen.utils.SchemaUtils;
7273
import org.slf4j.Logger;
7374
import org.slf4j.LoggerFactory;
7475

@@ -2515,7 +2516,7 @@ private String getPrimitiveType(Schema schema) {
25152516
// Note: the value of a free-form object cannot be an arbitrary type. Per OAS specification,
25162517
// it must be a map of string to values.
25172518
return "object";
2518-
} else if (schema.getProperties() != null && !schema.getProperties().isEmpty()) { // having property implies it's a model
2519+
} else if (SchemaUtils.hasProperties(schema)) { // having property implies it's a model
25192520
return "object";
25202521
} else if (ModelUtils.isAnyType(schema)) {
25212522
return "AnyType";
@@ -2707,8 +2708,8 @@ protected void updateModelForComposedSchema(CodegenModel m, Schema schema, Map<S
27072708
List<String> allRequired = new ArrayList<>();
27082709

27092710
// if schema has properties outside of allOf/oneOf/anyOf also add them to m
2710-
if (composed.getProperties() != null && !composed.getProperties().isEmpty()) {
2711-
if (composed.getOneOf() != null && !composed.getOneOf().isEmpty()) {
2711+
if (SchemaUtils.hasProperties(composed)) {
2712+
if (SchemaUtils.hasOneOf(composed)) {
27122713
LOGGER.warn("'oneOf' is intended to include only the additional optional OAS extension discriminator object. " +
27132714
"For more details, see https://json-schema.org/draft/2019-09/json-schema-core.html#rfc.section.9.2.1.3 and the OAS section on 'Composition and Inheritance'.");
27142715
}
@@ -3362,7 +3363,7 @@ private CodegenProperty discriminatorFound(String composedSchemaName, Schema sc,
33623363
}
33633364
}
33643365
}
3365-
if (composedSchema.getOneOf() != null && composedSchema.getOneOf().size() != 0) {
3366+
if (SchemaUtils.hasOneOf(composedSchema)) {
33663367
// All oneOf definitions must contain the discriminator
33673368
CodegenProperty cp = new CodegenProperty();
33683369
for (Object oneOf : composedSchema.getOneOf()) {
@@ -3388,7 +3389,7 @@ private CodegenProperty discriminatorFound(String composedSchemaName, Schema sc,
33883389
}
33893390
return cp;
33903391
}
3391-
if (composedSchema.getAnyOf() != null && composedSchema.getAnyOf().size() != 0) {
3392+
if (SchemaUtils.hasAnyOf(composedSchema)) {
33923393
// All anyOf definitions must contain the discriminator because a min of one must be selected
33933394
CodegenProperty cp = new CodegenProperty();
33943395
for (Object anyOf : composedSchema.getAnyOf()) {
@@ -3457,7 +3458,7 @@ private Discriminator recursiveGetDiscriminator(Schema sc, ArrayList<Schema> vis
34573458
}
34583459
}
34593460
}
3460-
if (composedSchema.getOneOf() != null && composedSchema.getOneOf().size() != 0) {
3461+
if (SchemaUtils.hasOneOf(composedSchema)) {
34613462
// All oneOf definitions must contain the discriminator
34623463
Integer hasDiscriminatorCnt = 0;
34633464
Integer hasNullTypeCnt = 0;
@@ -3792,7 +3793,7 @@ protected void addProperties(Map<String, Schema> properties, List<String> requir
37923793
}
37933794
if (ModelUtils.isComposedSchema(schema)) {
37943795
// fix issue #16797 and #15796, constructor fail by missing parent required params
3795-
if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
3796+
if (SchemaUtils.hasProperties(schema)) {
37963797
properties.putAll(schema.getProperties());
37973798
}
37983799

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

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import java.util.stream.Collectors;
3434
import org.apache.commons.lang3.StringUtils;
3535
import org.openapitools.codegen.utils.ModelUtils;
36+
import org.openapitools.codegen.utils.SchemaUtils;
3637
import org.slf4j.Logger;
3738
import org.slf4j.LoggerFactory;
3839

@@ -236,9 +237,9 @@ private boolean isModelNeeded(Schema schema, Set<Schema> visitedSchemas) {
236237
if (resolveInlineEnums && schema.getEnum() != null && schema.getEnum().size() > 0) {
237238
return true;
238239
}
239-
if (schema.getType() == null || "object".equals(schema.getType())) {
240+
if (schema.getType() == null || SchemaUtils.isObjectType(schema)) {
240241
// object or undeclared type with properties
241-
if (schema.getProperties() != null && schema.getProperties().size() > 0) {
242+
if (SchemaUtils.hasProperties(schema)) {
242243
return true;
243244
}
244245
}
@@ -275,10 +276,10 @@ private boolean isModelNeeded(Schema schema, Set<Schema> visitedSchemas) {
275276
return false;
276277
}
277278

278-
if (schema.getAnyOf() != null && !schema.getAnyOf().isEmpty()) {
279+
if (SchemaUtils.hasAnyOf(schema)) {
279280
return true;
280281
}
281-
if (schema.getOneOf() != null && !schema.getOneOf().isEmpty()) {
282+
if (SchemaUtils.hasOneOf(schema)) {
282283
return true;
283284
}
284285
}
@@ -297,7 +298,7 @@ private void gatherInlineModels(Schema schema, String modelPrefix) {
297298
if (schema.get$ref() != null) {
298299
// if ref already, no inline schemas should be present but check for
299300
// any to catch OpenAPI violations
300-
if (isModelNeeded(schema) || "object".equals(schema.getType()) ||
301+
if (isModelNeeded(schema) || SchemaUtils.isObjectType(schema) ||
301302
schema.getProperties() != null || schema.getAdditionalProperties() != null ||
302303
ModelUtils.isComposedSchema(schema)) {
303304
LOGGER.error("Illegal schema found with $ref combined with other properties," +
@@ -308,7 +309,7 @@ private void gatherInlineModels(Schema schema, String modelPrefix) {
308309
// Check object models / any type models / composed models for properties,
309310
// if the schema has a type defined that is not "object" it should not define
310311
// any properties
311-
if (schema.getType() == null || "object".equals(schema.getType())) {
312+
if (schema.getType() == null || SchemaUtils.isObjectType(schema)) {
312313
// Check properties and recurse, each property could be its own inline model
313314
Map<String, Schema> props = schema.getProperties();
314315
if (props != null) {
@@ -640,10 +641,8 @@ private void flattenComposedChildren(String key, List<Schema> children, boolean
640641
ListIterator<Schema> listIterator = children.listIterator();
641642
while (listIterator.hasNext()) {
642643
Schema component = listIterator.next();
643-
if ((component != null) &&
644-
(component.get$ref() == null) &&
645-
((component.getProperties() != null && !component.getProperties().isEmpty()) ||
646-
(component.getEnum() != null && !component.getEnum().isEmpty()))) {
644+
boolean componentDoesNotHaveRef = component != null && component.get$ref() == null;
645+
if (componentDoesNotHaveRef && (SchemaUtils.hasProperties(component) || SchemaUtils.hasEnum(component))) {
647646
// If a `title` attribute is defined in the inline schema, codegen uses it to name the
648647
// inline schema. Otherwise, we'll use the default naming such as InlineObject1, etc.
649648
// We know that this is not the best way to name the model.
@@ -839,7 +838,7 @@ private void flattenProperties(OpenAPI openAPI, Map<String, Schema> properties,
839838
Schema inner = ModelUtils.getSchemaItems(property);
840839
if (ModelUtils.isObjectSchema(inner)) {
841840
Schema op = inner;
842-
if (op.getProperties() != null && op.getProperties().size() > 0) {
841+
if (SchemaUtils.hasProperties(op)) {
843842
flattenProperties(openAPI, op.getProperties(), path);
844843
String modelName = resolveModelName(op.getTitle(), path + "_" + key);
845844
Schema innerModel = modelFromProperty(openAPI, op, modelName);
@@ -869,7 +868,7 @@ private void flattenProperties(OpenAPI openAPI, Map<String, Schema> properties,
869868
Schema inner = ModelUtils.getAdditionalProperties(property);
870869
if (ModelUtils.isObjectSchema(inner)) {
871870
Schema op = inner;
872-
if (op.getProperties() != null && op.getProperties().size() > 0) {
871+
if (SchemaUtils.hasProperties(op)) {
873872
flattenProperties(openAPI, op.getProperties(), path);
874873
String modelName = resolveModelName(op.getTitle(), path + "_" + key);
875874
Schema innerModel = modelFromProperty(openAPI, op, modelName);

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

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import io.swagger.v3.oas.models.security.SecurityScheme;
3030
import org.apache.commons.lang3.StringUtils;
3131
import org.openapitools.codegen.utils.ModelUtils;
32+
import org.openapitools.codegen.utils.SchemaUtils;
3233
import org.slf4j.Logger;
3334
import org.slf4j.LoggerFactory;
3435

@@ -760,19 +761,19 @@ public Schema normalizeSchema(Schema schema, Set<Schema> visitedSchemas) {
760761
schema = normalizeComplexComposedSchema(schema, visitedSchemas);
761762
}
762763

763-
if (schema.getAllOf() != null && !schema.getAllOf().isEmpty()) {
764+
if (SchemaUtils.hasAllOf(schema)) {
764765
return normalizeAllOf(schema, visitedSchemas);
765766
}
766767

767-
if (schema.getOneOf() != null && !schema.getOneOf().isEmpty()) {
768+
if (SchemaUtils.hasOneOf(schema)) {
768769
return normalizeOneOf(schema, visitedSchemas);
769770
}
770771

771-
if (schema.getAnyOf() != null && !schema.getAnyOf().isEmpty()) {
772+
if (SchemaUtils.hasAnyOf(schema)) {
772773
return normalizeAnyOf(schema, visitedSchemas);
773774
}
774775

775-
if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
776+
if (SchemaUtils.hasProperties(schema)) {
776777
normalizeProperties(schema, visitedSchemas);
777778
}
778779

@@ -781,7 +782,7 @@ public Schema normalizeSchema(Schema schema, Set<Schema> visitedSchemas) {
781782
}
782783

783784
return schema;
784-
} else if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
785+
} else if (SchemaUtils.hasProperties(schema)) {
785786
normalizeProperties(schema, visitedSchemas);
786787
} else if (schema.getAdditionalProperties() instanceof Schema) { // map
787788
normalizeMapSchema(schema);
@@ -1109,7 +1110,7 @@ protected Schema normalizeAnyOf(Schema schema, Set<Schema> visitedSchemas) {
11091110

11101111
protected Schema normalizeComplexComposedSchema(Schema schema, Set<Schema> visitedSchemas) {
11111112
// loop through properties, if any
1112-
if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
1113+
if (SchemaUtils.hasProperties(schema)) {
11131114
normalizeProperties(schema, visitedSchemas);
11141115
}
11151116

@@ -1294,10 +1295,9 @@ protected void processRemoveAnyOfOneOfAndKeepPropertiesOnly(Schema schema) {
12941295
return;
12951296
}
12961297

1297-
if (((schema.getOneOf() != null && !schema.getOneOf().isEmpty())
1298-
|| (schema.getAnyOf() != null && !schema.getAnyOf().isEmpty())) // has anyOf or oneOf
1299-
&& (schema.getProperties() != null && !schema.getProperties().isEmpty()) // has properties
1300-
&& schema.getAllOf() == null) { // not allOf
1298+
boolean hasAnyOfOrOneOf = SchemaUtils.hasOneOf(schema) || SchemaUtils.hasAnyOf(schema);
1299+
boolean notAllOf = schema.getAllOf() == null;
1300+
if (hasAnyOfOrOneOf && SchemaUtils.hasProperties(schema) && notAllOf) {
13011301
// clear oneOf, anyOf
13021302
schema.setOneOf(null);
13031303
schema.setAnyOf(null);
@@ -1374,9 +1374,7 @@ protected Schema processSimplifyAnyOfEnum(Schema schema) {
13741374
if (schema.getAnyOf() == null || schema.getAnyOf().isEmpty()) {
13751375
return schema;
13761376
}
1377-
if(schema.getOneOf() != null && !schema.getOneOf().isEmpty() ||
1378-
schema.getAllOf() != null && !schema.getAllOf().isEmpty() ||
1379-
schema.getNot() != null) {
1377+
if(SchemaUtils.hasOneOf(schema) || SchemaUtils.hasAllOf(schema) || schema.getNot() != null) {
13801378
//only convert to enum if anyOf is the only composition
13811379
return schema;
13821380
}
@@ -2109,7 +2107,7 @@ protected void processNormalizeOtherThanObjectWithProperties(Schema schema) {
21092107
// Check object models / any type models / composed models for properties,
21102108
// if the schema has a type defined that is not "object" it should not define
21112109
// any properties
2112-
if (schema.getType() != null && !"object".equals(schema.getType())) {
2110+
if (schema.getType() != null && !SchemaUtils.isObjectType(schema)) {
21132111
schema.setProperties(null);
21142112
}
21152113
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
import org.openapitools.codegen.model.OperationsMap;
5555
import org.openapitools.codegen.utils.CamelizeOption;
5656
import org.openapitools.codegen.utils.ModelUtils;
57+
import org.openapitools.codegen.utils.SchemaUtils;
5758
import org.slf4j.Logger;
5859
import org.slf4j.LoggerFactory;
5960

@@ -1383,7 +1384,7 @@ public String toDefaultValue(CodegenProperty cp, Schema schema) {
13831384
}
13841385
return toArrayDefaultValue(cp, schema);
13851386
} else if (ModelUtils.isMapSchema(schema) && !(ModelUtils.isComposedSchema(schema))) {
1386-
if (schema.getProperties() != null && schema.getProperties().size() > 0) {
1387+
if (SchemaUtils.hasProperties(schema)) {
13871388
// object is complex object with free-form additional properties
13881389
if (schema.getDefault() != null) {
13891390
return super.toDefaultValue(schema);

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import org.openapitools.codegen.model.OperationMap;
3030
import org.openapitools.codegen.model.OperationsMap;
3131
import org.openapitools.codegen.utils.ModelUtils;
32+
import org.openapitools.codegen.utils.SchemaUtils;
3233
import org.slf4j.Logger;
3334
import org.slf4j.LoggerFactory;
3435

@@ -406,7 +407,7 @@ public String getSchemaType(Schema p) {
406407
openAPIType = "UNKNOWN_OPENAPI_TYPE";
407408
}
408409

409-
if ((p.getAnyOf() != null && !p.getAnyOf().isEmpty()) || (p.getOneOf() != null && !p.getOneOf().isEmpty())) {
410+
if (SchemaUtils.hasAnyOf(p) || SchemaUtils.hasOneOf(p)) {
410411
return openAPIType;
411412
}
412413

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import org.openapitools.codegen.model.OperationMap;
3232
import org.openapitools.codegen.model.OperationsMap;
3333
import org.openapitools.codegen.utils.ModelUtils;
34+
import org.openapitools.codegen.utils.SchemaUtils;
3435
import org.slf4j.Logger;
3536
import org.slf4j.LoggerFactory;
3637

@@ -512,7 +513,7 @@ private String toExampleValueRecursive(Schema schema, List<Schema> includedSchem
512513

513514
// if required and optionals
514515
List<String> reqs = new ArrayList<>();
515-
if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
516+
if (SchemaUtils.hasProperties(schema)) {
516517
for (Object toAdd : schema.getProperties().keySet()) {
517518
reqs.add((String) toAdd);
518519
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.openapitools.codegen.model.OperationMap;
3131
import org.openapitools.codegen.model.OperationsMap;
3232
import org.openapitools.codegen.utils.ModelUtils;
33+
import org.openapitools.codegen.utils.SchemaUtils;
3334
import org.slf4j.Logger;
3435
import org.slf4j.LoggerFactory;
3536

@@ -483,7 +484,7 @@ private String toExampleValueRecursive(Schema schema, List<Schema> includedSchem
483484

484485
// if required and optionals
485486
List<String> reqs = new ArrayList<>();
486-
if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
487+
if (SchemaUtils.hasProperties(schema)) {
487488
for (Object toAdd : schema.getProperties().keySet()) {
488489
reqs.add((String) toAdd);
489490
}

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.openapitools.codegen.model.OperationsMap;
4949
import org.openapitools.codegen.utils.CamelizeOption;
5050
import org.openapitools.codegen.utils.ModelUtils;
51+
import org.openapitools.codegen.utils.SchemaUtils;
5152
import org.openapitools.codegen.utils.StringUtils;
5253
import org.slf4j.Logger;
5354
import org.slf4j.LoggerFactory;
@@ -980,7 +981,7 @@ private void processNestedSchemas(Schema schema, String parentName, int depth) {
980981
// Set title for nested inline schemas
981982
if (propSchema.getTitle() == null && propSchema.get$ref() == null) {
982983
// For nested objects, create a meaningful name
983-
if ("object".equals(propSchema.getType()) || (propSchema.getType() == null && propSchema.getProperties() != null)) {
984+
if (isNestedObject(propSchema)) {
984985
String title = toPascalCase(parentName + "_" + propertyName);
985986
propSchema.setTitle(title);
986987

@@ -995,7 +996,7 @@ private void processNestedSchemas(Schema schema, String parentName, int depth) {
995996
if (schema.getItems() != null) {
996997
Schema itemSchema = schema.getItems();
997998
if (itemSchema.getTitle() == null && itemSchema.get$ref() == null) {
998-
if ("object".equals(itemSchema.getType()) || (itemSchema.getType() == null && itemSchema.getProperties() != null)) {
999+
if (isNestedObject(itemSchema)) {
9991000
String title = toPascalCase(parentName + "_item");
10001001
itemSchema.setTitle(title);
10011002
processNestedSchemas(itemSchema, title, depth + 1);
@@ -1007,7 +1008,7 @@ private void processNestedSchemas(Schema schema, String parentName, int depth) {
10071008
if (schema.getAdditionalProperties() instanceof Schema) {
10081009
Schema additionalSchema = (Schema) schema.getAdditionalProperties();
10091010
if (additionalSchema.getTitle() == null && additionalSchema.get$ref() == null) {
1010-
if ("object".equals(additionalSchema.getType()) || (additionalSchema.getType() == null && additionalSchema.getProperties() != null)) {
1011+
if (isNestedObject(additionalSchema)) {
10111012
String title = toPascalCase(parentName + "_additional");
10121013
additionalSchema.setTitle(title);
10131014
processNestedSchemas(additionalSchema, title, depth + 1);
@@ -1499,7 +1500,7 @@ public String toApiFilename(String name) {
14991500
@Override
15001501
@SuppressWarnings({"rawtypes", "unchecked"})
15011502
public String getTypeDeclaration(Schema p) {
1502-
if (p.getOneOf() != null && !p.getOneOf().isEmpty()) {
1503+
if (SchemaUtils.hasOneOf(p)) {
15031504
// For oneOf, map to std::variant of possible types
15041505
StringBuilder variant = new StringBuilder("std::variant<");
15051506
List<Schema> schemas = p.getOneOf();
@@ -1509,7 +1510,7 @@ public String getTypeDeclaration(Schema p) {
15091510
}
15101511
variant.append(">");
15111512
return variant.toString();
1512-
} else if (p.getAnyOf() != null && !p.getAnyOf().isEmpty()) {
1513+
} else if (SchemaUtils.hasAnyOf(p)) {
15131514
// For anyOf, also use std::variant to handle multiple possible types
15141515
StringBuilder variant = new StringBuilder("std::variant<");
15151516
List<Schema> schemas = p.getAnyOf();
@@ -1619,7 +1620,7 @@ else if (refCount > 1 || mergedVars.size() > 0) {
16191620
}
16201621

16211622
// Handle oneOf/anyOf schemas - generate std::variant type alias instead of class
1622-
if (schema.getOneOf() != null && !schema.getOneOf().isEmpty()) {
1623+
if (SchemaUtils.hasOneOf(schema)) {
16231624
model.vendorExtensions.put("isOneOfSchema", true);
16241625
model.vendorExtensions.put("hasVariant", true);
16251626
List<String> variantTypes = new ArrayList<>();
@@ -2570,4 +2571,8 @@ public Map<String, Object> postProcessSupportingFileData(Map<String, Object> obj
25702571
}
25712572
return super.postProcessSupportingFileData(objs);
25722573
}
2574+
2575+
private static boolean isNestedObject(Schema<?> schema) {
2576+
return SchemaUtils.isObjectType(schema) || (schema.getType() == null && schema.getProperties() != null);
2577+
}
25732578
}

0 commit comments

Comments
 (0)