Skip to content

Commit 4f27939

Browse files
[core] Add model cache to speed up code generation (#7250)
1 parent 8cd503f commit 4f27939

File tree

4 files changed

+162
-47
lines changed

4 files changed

+162
-47
lines changed

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

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ apiTemplateFiles are for API outputs only (controllers/handlers).
247247
// make openapi available to all methods
248248
protected OpenAPI openAPI;
249249

250+
// A cache to efficiently lookup a Schema instance based on the return value of `toModelName()`.
251+
private Map<String, Schema> modelNameToSchemaCache;
252+
250253
public List<CliOption> cliOptions() {
251254
return cliOptions;
252255
}
@@ -450,6 +453,23 @@ public Map<String, Object> postProcessAllModels(Map<String, Object> objs) {
450453
return objs;
451454
}
452455

456+
/**
457+
* Return a map from model name to Schema for efficient lookup.
458+
*
459+
* @return map from model name to Schema.
460+
*/
461+
protected Map<String, Schema> getModelNameToSchemaCache() {
462+
if (modelNameToSchemaCache == null) {
463+
// Create a cache to efficiently lookup schema based on model name.
464+
Map<String, Schema> m = new HashMap<String, Schema>();
465+
ModelUtils.getSchemas(openAPI).forEach((key, schema) -> {
466+
m.put(toModelName(key), schema);
467+
});
468+
modelNameToSchemaCache = Collections.unmodifiableMap(m);
469+
}
470+
return modelNameToSchemaCache;
471+
}
472+
453473
/**
454474
* Index all CodegenModels by model name.
455475
*
@@ -1293,14 +1313,13 @@ public String toOperationId(String operationId) {
12931313
* @param name the variable name
12941314
* @return the sanitized variable name
12951315
*/
1296-
public String toVarName(String name) {
1316+
public String toVarName(final String name) {
12971317
if (reservedWords.contains(name)) {
12981318
return escapeReservedWord(name);
12991319
} else if (((CharSequence) name).chars().anyMatch(character -> specialCharReplacements.keySet().contains("" + ((char) character)))) {
13001320
return escape(name, specialCharReplacements, null, null);
1301-
} else {
1302-
return name;
13031321
}
1322+
return name;
13041323
}
13051324

13061325
/**
@@ -1318,6 +1337,7 @@ public String toParamName(String name) {
13181337
return escape(name, specialCharReplacements, null, null);
13191338
}
13201339
return name;
1340+
13211341
}
13221342

13231343
/**
@@ -2195,7 +2215,8 @@ public String toApiName(String name) {
21952215
}
21962216

21972217
/**
2198-
* Output the proper model name (capitalized).
2218+
* Converts the OpenAPI schema name to a model name suitable for the current code generator.
2219+
* May be overriden for each programming language.
21992220
* In case the name belongs to the TypeSystem it won't be renamed.
22002221
*
22012222
* @param name the name of the model
@@ -2205,8 +2226,33 @@ public String toModelName(final String name) {
22052226
return camelize(modelNamePrefix + "_" + name + "_" + modelNameSuffix);
22062227
}
22072228

2229+
private static class NamedSchema {
2230+
private NamedSchema(String name, Schema s) {
2231+
this.name = name;
2232+
this.schema = s;
2233+
}
2234+
private String name;
2235+
private Schema schema;
2236+
2237+
@Override
2238+
public boolean equals(Object o) {
2239+
if (this == o) return true;
2240+
if (o == null || getClass() != o.getClass()) return false;
2241+
NamedSchema that = (NamedSchema) o;
2242+
return Objects.equals(name, that.name) &&
2243+
Objects.equals(schema, that.schema);
2244+
}
2245+
2246+
@Override
2247+
public int hashCode() {
2248+
return Objects.hash(name, schema);
2249+
}
2250+
}
2251+
2252+
Map<NamedSchema, CodegenProperty> schemaCodegenPropertyCache = new HashMap<NamedSchema, CodegenProperty>();
2253+
22082254
/**
2209-
* Convert OAS Model object to Codegen Model object
2255+
* Convert OAS Model object to Codegen Model object.
22102256
*
22112257
* @param name the name of the model
22122258
* @param schema OAS Model object
@@ -2565,7 +2611,6 @@ public int compare(CodegenProperty one, CodegenProperty another) {
25652611
postProcessModelProperty(m, prop);
25662612
}
25672613
}
2568-
25692614
return m;
25702615
}
25712616

@@ -2984,7 +3029,13 @@ public String getterAndSetterCapitalize(String name) {
29843029
}
29853030

29863031
/**
2987-
* Convert OAS Property object to Codegen Property object
3032+
* Convert OAS Property object to Codegen Property object.
3033+
*
3034+
* The return value is cached. An internal cache is looked up to determine
3035+
* if the CodegenProperty return value has already been instantiated for
3036+
* the (String name, Schema p) arguments.
3037+
* Any subsequent processing of the CodegenModel return value must be idempotent
3038+
* for a given (String name, Schema schema).
29883039
*
29893040
* @param name name of the property
29903041
* @param p OAS property schema
@@ -2996,7 +3047,12 @@ public CodegenProperty fromProperty(String name, Schema p) {
29963047
return null;
29973048
}
29983049
LOGGER.debug("debugging fromProperty for " + name + " : " + p);
2999-
3050+
NamedSchema ns = new NamedSchema(name, p);
3051+
CodegenProperty cpc = schemaCodegenPropertyCache.get(ns);
3052+
if (cpc != null) {
3053+
LOGGER.debug("Cached fromProperty for " + name + " : " + p.getName());
3054+
return cpc;
3055+
}
30003056
// unalias schema
30013057
p = unaliasSchema(p, importMapping);
30023058

@@ -3296,6 +3352,7 @@ public CodegenProperty fromProperty(String name, Schema p) {
32963352
}
32973353

32983354
LOGGER.debug("debugging from property return: " + property);
3355+
schemaCodegenPropertyCache.put(ns, property);
32993356
return property;
33003357
}
33013358

@@ -4762,7 +4819,6 @@ private void addVars(CodegenModel m, List<CodegenProperty> vars, Map<String, Sch
47624819

47634820
final String key = entry.getKey();
47644821
final Schema prop = entry.getValue();
4765-
47664822
if (prop == null) {
47674823
LOGGER.warn("Please report the issue. There shouldn't be null property for " + key);
47684824
} else {
@@ -6382,14 +6438,17 @@ protected void modifyFeatureSet(Consumer<FeatureSet.Builder> processor) {
63826438
.featureSet(builder.build()).build();
63836439
}
63846440

6441+
/**
6442+
* An map entry for cached sanitized names.
6443+
*/
63856444
private static class SanitizeNameOptions {
63866445
public SanitizeNameOptions(String name, String removeCharRegEx, List<String> exceptions) {
63876446
this.name = name;
63886447
this.removeCharRegEx = removeCharRegEx;
63896448
if (exceptions != null) {
63906449
this.exceptions = Collections.unmodifiableList(exceptions);
63916450
} else {
6392-
this.exceptions = Collections.unmodifiableList(new ArrayList<>());
6451+
this.exceptions = Collections.emptyList();
63936452
}
63946453
}
63956454

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

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -493,19 +493,16 @@ public void updateCodegenPropertyEnum(CodegenProperty var) {
493493
}
494494

495495
String varDataType = var.mostInnerItems != null ? var.mostInnerItems.dataType : var.dataType;
496-
Optional<Schema> referencedSchema = ModelUtils.getSchemas(openAPI).entrySet().stream()
497-
.filter(entry -> Objects.equals(varDataType, toModelName(entry.getKey())))
498-
.map(Map.Entry::getValue)
499-
.findFirst();
500-
String dataType = (referencedSchema.isPresent()) ? getTypeDeclaration(referencedSchema.get()) : varDataType;
496+
Schema referencedSchema = getModelNameToSchemaCache().get(varDataType);
497+
String dataType = (referencedSchema != null) ? getTypeDeclaration(referencedSchema) : varDataType;
501498

502499
// put "enumVars" map into `allowableValues", including `name` and `value`
503500
List<Map<String, Object>> enumVars = buildEnumVars(values, dataType);
504501

505502
// if "x-enum-varnames" or "x-enum-descriptions" defined, update varnames
506503
Map<String, Object> extensions = var.mostInnerItems != null ? var.mostInnerItems.getVendorExtensions() : var.getVendorExtensions();
507-
if (referencedSchema.isPresent()) {
508-
extensions = referencedSchema.get().getExtensions();
504+
if (referencedSchema != null) {
505+
extensions = referencedSchema.getExtensions();
509506
}
510507
updateEnumVarsWithExtensions(enumVars, extensions);
511508
allowableValues.put("enumVars", enumVars);

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,7 @@ public static Schema unaliasSchema(OpenAPI openAPI,
10541054
/**
10551055
* Get the actual schema from aliases. If the provided schema is not an alias, the schema itself will be returned.
10561056
*
1057-
* @param openAPI specification being checked
1057+
* @param openAPI OpenAPI document containing the schemas.
10581058
* @param schema schema (alias or direct reference)
10591059
* @param importMappings mappings of external types to be omitted by unaliasing
10601060
* @return actual schema

0 commit comments

Comments
 (0)