mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-05-28 20:40:52 +00:00
Add OpenAPI Normalizer (#14172)
* add x-parent support * add docstring * add openapi normalizer rule to use ref as parent in allof * add openapi normalizer with 1 rule * revise wordings * fix javadoc warnings * better test * fix docstring * minor update * minor improvements * fix typo
This commit is contained in:
parent
3a8265b6ee
commit
b71aecbe9e
@ -451,3 +451,16 @@ Another useful option is `inlineSchemaNameDefaults`, which allows you to customi
|
|||||||
```
|
```
|
||||||
|
|
||||||
Note: Only arrayItemSuffix, mapItemSuffix are supported at the moment. `SKIP_SCHEMA_REUSE=true` is a special value to skip reusing inline schemas.
|
Note: Only arrayItemSuffix, mapItemSuffix are supported at the moment. `SKIP_SCHEMA_REUSE=true` is a special value to skip reusing inline schemas.
|
||||||
|
|
||||||
|
## OpenAPI Normalizer
|
||||||
|
|
||||||
|
OpenAPI Normalizer (off by default) transforms the input OpenAPI doc/spec (which may not perfectly conform to the specification) to make it workable with OpenAPI Generator. Here is a list of rules supported:
|
||||||
|
|
||||||
|
- `REF_AS_PARENT_IN_ALLOF`: when set to `true`, child schemas in `allOf` is considered a parent if it's a `$ref` (instead of inline schema)
|
||||||
|
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
java -jar modules/openapi-generator-cli/target/openapi-generator-cli.jar generate -g java -i modules/openapi-generator/src/test/resources/3_0/allOf_extension_parent.yaml -o /tmp/java-okhttp/ --additional-properties hideGenerationTimestamp="true" --openapi-normalizer REF_AS_PARENT_IN_ALLOF=true
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -80,6 +80,9 @@ public class ConfigHelp extends OpenApiGeneratorCommand {
|
|||||||
@Option(name = {"--inline-schema-name-defaults"}, title = "inline schema name defaults", description = "default values used when naming inline schema name")
|
@Option(name = {"--inline-schema-name-defaults"}, title = "inline schema name defaults", description = "default values used when naming inline schema name")
|
||||||
private Boolean inlineSchemaNameDefaults;
|
private Boolean inlineSchemaNameDefaults;
|
||||||
|
|
||||||
|
@Option(name = {"--openapi-normalizer"}, title = "openapi normalizer rules", description = "displays the OpenAPI normalizer rules (none)")
|
||||||
|
private Boolean openapiNormalizer;
|
||||||
|
|
||||||
@Option(name = {"--metadata"}, title = "metadata", description = "displays the generator metadata like the help txt for the generator and generator type etc")
|
@Option(name = {"--metadata"}, title = "metadata", description = "displays the generator metadata like the help txt for the generator and generator type etc")
|
||||||
private Boolean metadata;
|
private Boolean metadata;
|
||||||
|
|
||||||
@ -494,6 +497,18 @@ public class ConfigHelp extends OpenApiGeneratorCommand {
|
|||||||
sb.append(newline);
|
sb.append(newline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Boolean.TRUE.equals(openapiNormalizer)) {
|
||||||
|
sb.append(newline).append("OPENAPI NORMALIZER RULES").append(newline).append(newline);
|
||||||
|
Map<String, String> map = config.openapiNormalizer()
|
||||||
|
.entrySet()
|
||||||
|
.stream()
|
||||||
|
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> {
|
||||||
|
throw new IllegalStateException(String.format(Locale.ROOT, "Duplicated options! %s and %s", a, b));
|
||||||
|
}, TreeMap::new));
|
||||||
|
writePlainTextFromMap(sb, map, optIndent, optNestedIndent, "OpenAPI normalizer rule", "Set to");
|
||||||
|
sb.append(newline);
|
||||||
|
}
|
||||||
|
|
||||||
if (Boolean.TRUE.equals(instantiationTypes)) {
|
if (Boolean.TRUE.equals(instantiationTypes)) {
|
||||||
sb.append(newline).append("INSTANTIATION TYPES").append(newline).append(newline);
|
sb.append(newline).append("INSTANTIATION TYPES").append(newline).append(newline);
|
||||||
Map<String, String> map = config.instantiationTypes()
|
Map<String, String> map = config.instantiationTypes()
|
||||||
|
@ -180,6 +180,13 @@ public class Generate extends OpenApiGeneratorCommand {
|
|||||||
+ " ONLY arrayItemSuffix, mapItemSuffix are supported at the moment. `SKIP_SCHEMA_REUSE=true` is a special value to skip reusing inline schemas.")
|
+ " ONLY arrayItemSuffix, mapItemSuffix are supported at the moment. `SKIP_SCHEMA_REUSE=true` is a special value to skip reusing inline schemas.")
|
||||||
private List<String> inlineSchemaNameDefaults = new ArrayList<>();
|
private List<String> inlineSchemaNameDefaults = new ArrayList<>();
|
||||||
|
|
||||||
|
@Option(
|
||||||
|
name = {"--openapi-normalizer"},
|
||||||
|
title = "OpenAPI normalizer rules",
|
||||||
|
description = "specifies the rules to be enabled in OpenAPI normalizer in the form of RULE_1=true,RULE_2=original."
|
||||||
|
+ " You can also have multiple occurrences of this option.")
|
||||||
|
private List<String> openapiNormalizer = new ArrayList<>();
|
||||||
|
|
||||||
@Option(
|
@Option(
|
||||||
name = {"--server-variables"},
|
name = {"--server-variables"},
|
||||||
title = "server variables",
|
title = "server variables",
|
||||||
@ -447,6 +454,7 @@ public class Generate extends OpenApiGeneratorCommand {
|
|||||||
applySchemaMappingsKvpList(schemaMappings, configurator);
|
applySchemaMappingsKvpList(schemaMappings, configurator);
|
||||||
applyInlineSchemaNameMappingsKvpList(inlineSchemaNameMappings, configurator);
|
applyInlineSchemaNameMappingsKvpList(inlineSchemaNameMappings, configurator);
|
||||||
applyInlineSchemaNameDefaultsKvpList(inlineSchemaNameDefaults, configurator);
|
applyInlineSchemaNameDefaultsKvpList(inlineSchemaNameDefaults, configurator);
|
||||||
|
applyOpenAPINormalizerKvpList(openapiNormalizer, configurator);
|
||||||
applyTypeMappingsKvpList(typeMappings, configurator);
|
applyTypeMappingsKvpList(typeMappings, configurator);
|
||||||
applyAdditionalPropertiesKvpList(additionalProperties, configurator);
|
applyAdditionalPropertiesKvpList(additionalProperties, configurator);
|
||||||
applyLanguageSpecificPrimitivesCsvList(languageSpecificPrimitives, configurator);
|
applyLanguageSpecificPrimitivesCsvList(languageSpecificPrimitives, configurator);
|
||||||
|
@ -53,6 +53,7 @@ public final class GeneratorSettings implements Serializable {
|
|||||||
private final Map<String, String> schemaMappings;
|
private final Map<String, String> schemaMappings;
|
||||||
private final Map<String, String> inlineSchemaNameMappings;
|
private final Map<String, String> inlineSchemaNameMappings;
|
||||||
private final Map<String, String> inlineSchemaNameDefaults;
|
private final Map<String, String> inlineSchemaNameDefaults;
|
||||||
|
private final Map<String, String> openapiNormalizer;
|
||||||
private final Set<String> languageSpecificPrimitives;
|
private final Set<String> languageSpecificPrimitives;
|
||||||
private final Map<String, String> reservedWordsMappings;
|
private final Map<String, String> reservedWordsMappings;
|
||||||
private final Map<String, String> serverVariables;
|
private final Map<String, String> serverVariables;
|
||||||
@ -264,6 +265,15 @@ public final class GeneratorSettings implements Serializable {
|
|||||||
return inlineSchemaNameDefaults;
|
return inlineSchemaNameDefaults;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets OpenAPI normalizer rules
|
||||||
|
*
|
||||||
|
* @return a map of rules
|
||||||
|
*/
|
||||||
|
public Map<String, String> getOpenAPINormalizer() {
|
||||||
|
return openapiNormalizer;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets language specific primitives. These are in addition to the "base" primitives defined in a generator.
|
* Gets language specific primitives. These are in addition to the "base" primitives defined in a generator.
|
||||||
* <p>
|
* <p>
|
||||||
@ -382,6 +392,7 @@ public final class GeneratorSettings implements Serializable {
|
|||||||
schemaMappings = Collections.unmodifiableMap(builder.schemaMappings);
|
schemaMappings = Collections.unmodifiableMap(builder.schemaMappings);
|
||||||
inlineSchemaNameMappings = Collections.unmodifiableMap(builder.inlineSchemaNameMappings);
|
inlineSchemaNameMappings = Collections.unmodifiableMap(builder.inlineSchemaNameMappings);
|
||||||
inlineSchemaNameDefaults = Collections.unmodifiableMap(builder.inlineSchemaNameDefaults);
|
inlineSchemaNameDefaults = Collections.unmodifiableMap(builder.inlineSchemaNameDefaults);
|
||||||
|
openapiNormalizer = Collections.unmodifiableMap(builder.openapiNormalizer);
|
||||||
languageSpecificPrimitives = Collections.unmodifiableSet(builder.languageSpecificPrimitives);
|
languageSpecificPrimitives = Collections.unmodifiableSet(builder.languageSpecificPrimitives);
|
||||||
reservedWordsMappings = Collections.unmodifiableMap(builder.reservedWordsMappings);
|
reservedWordsMappings = Collections.unmodifiableMap(builder.reservedWordsMappings);
|
||||||
serverVariables = Collections.unmodifiableMap(builder.serverVariables);
|
serverVariables = Collections.unmodifiableMap(builder.serverVariables);
|
||||||
@ -455,6 +466,7 @@ public final class GeneratorSettings implements Serializable {
|
|||||||
schemaMappings = Collections.unmodifiableMap(new HashMap<>(0));
|
schemaMappings = Collections.unmodifiableMap(new HashMap<>(0));
|
||||||
inlineSchemaNameMappings = Collections.unmodifiableMap(new HashMap<>(0));
|
inlineSchemaNameMappings = Collections.unmodifiableMap(new HashMap<>(0));
|
||||||
inlineSchemaNameDefaults = Collections.unmodifiableMap(new HashMap<>(0));
|
inlineSchemaNameDefaults = Collections.unmodifiableMap(new HashMap<>(0));
|
||||||
|
openapiNormalizer = Collections.unmodifiableMap(new HashMap<>(0));
|
||||||
languageSpecificPrimitives = Collections.unmodifiableSet(new HashSet<>(0));
|
languageSpecificPrimitives = Collections.unmodifiableSet(new HashSet<>(0));
|
||||||
reservedWordsMappings = Collections.unmodifiableMap(new HashMap<>(0));
|
reservedWordsMappings = Collections.unmodifiableMap(new HashMap<>(0));
|
||||||
serverVariables = Collections.unmodifiableMap(new HashMap<>(0));
|
serverVariables = Collections.unmodifiableMap(new HashMap<>(0));
|
||||||
@ -515,6 +527,9 @@ public final class GeneratorSettings implements Serializable {
|
|||||||
if (copy.getInlineSchemaNameDefaults() != null) {
|
if (copy.getInlineSchemaNameDefaults() != null) {
|
||||||
builder.inlineSchemaNameDefaults.putAll(copy.getInlineSchemaNameDefaults());
|
builder.inlineSchemaNameDefaults.putAll(copy.getInlineSchemaNameDefaults());
|
||||||
}
|
}
|
||||||
|
if (copy.getOpenAPINormalizer() != null) {
|
||||||
|
builder.openapiNormalizer.putAll(copy.getOpenAPINormalizer());
|
||||||
|
}
|
||||||
if (copy.getLanguageSpecificPrimitives() != null) {
|
if (copy.getLanguageSpecificPrimitives() != null) {
|
||||||
builder.languageSpecificPrimitives.addAll(copy.getLanguageSpecificPrimitives());
|
builder.languageSpecificPrimitives.addAll(copy.getLanguageSpecificPrimitives());
|
||||||
}
|
}
|
||||||
@ -557,6 +572,7 @@ public final class GeneratorSettings implements Serializable {
|
|||||||
private Map<String, String> schemaMappings;
|
private Map<String, String> schemaMappings;
|
||||||
private Map<String, String> inlineSchemaNameMappings;
|
private Map<String, String> inlineSchemaNameMappings;
|
||||||
private Map<String, String> inlineSchemaNameDefaults;
|
private Map<String, String> inlineSchemaNameDefaults;
|
||||||
|
private Map<String, String> openapiNormalizer;
|
||||||
private Set<String> languageSpecificPrimitives;
|
private Set<String> languageSpecificPrimitives;
|
||||||
private Map<String, String> reservedWordsMappings;
|
private Map<String, String> reservedWordsMappings;
|
||||||
private Map<String, String> serverVariables;
|
private Map<String, String> serverVariables;
|
||||||
@ -577,6 +593,7 @@ public final class GeneratorSettings implements Serializable {
|
|||||||
schemaMappings = new HashMap<>();
|
schemaMappings = new HashMap<>();
|
||||||
inlineSchemaNameMappings = new HashMap<>();
|
inlineSchemaNameMappings = new HashMap<>();
|
||||||
inlineSchemaNameDefaults = new HashMap<>();
|
inlineSchemaNameDefaults = new HashMap<>();
|
||||||
|
openapiNormalizer = new HashMap<>();
|
||||||
languageSpecificPrimitives = new HashSet<>();
|
languageSpecificPrimitives = new HashSet<>();
|
||||||
reservedWordsMappings = new HashMap<>();
|
reservedWordsMappings = new HashMap<>();
|
||||||
serverVariables = new HashMap<>();
|
serverVariables = new HashMap<>();
|
||||||
@ -897,6 +914,32 @@ public final class GeneratorSettings implements Serializable {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the {@code openapiNormalizer} and returns a reference to this Builder so that the methods can be chained together.
|
||||||
|
*
|
||||||
|
* @param openapiNormalizer the {@code openapiNormalizer} to set
|
||||||
|
* @return a reference to this Builder
|
||||||
|
*/
|
||||||
|
public Builder withOpenAPINormalizer(Map<String, String> openapiNormalizer) {
|
||||||
|
this.openapiNormalizer = openapiNormalizer;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a single {@code openapiNormalizer} and returns a reference to this Builder so that the methods can be chained together.
|
||||||
|
*
|
||||||
|
* @param key A key for the OpenAPI normalizer rule
|
||||||
|
* @param value The value of the OpenAPI normalizer rule
|
||||||
|
* @return a reference to this Builder
|
||||||
|
*/
|
||||||
|
public Builder withOpenAPINormalizer(String key, String value) {
|
||||||
|
if (this.openapiNormalizer == null) {
|
||||||
|
this.openapiNormalizer = new HashMap<>();
|
||||||
|
}
|
||||||
|
this.openapiNormalizer.put(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@code languageSpecificPrimitives} and returns a reference to this Builder so that the methods can be chained together.
|
* Sets the {@code languageSpecificPrimitives} and returns a reference to this Builder so that the methods can be chained together.
|
||||||
*
|
*
|
||||||
@ -1085,6 +1128,7 @@ public final class GeneratorSettings implements Serializable {
|
|||||||
Objects.equals(getSchemaMappings(), that.getSchemaMappings()) &&
|
Objects.equals(getSchemaMappings(), that.getSchemaMappings()) &&
|
||||||
Objects.equals(getInlineSchemaNameMappings(), that.getInlineSchemaNameMappings()) &&
|
Objects.equals(getInlineSchemaNameMappings(), that.getInlineSchemaNameMappings()) &&
|
||||||
Objects.equals(getInlineSchemaNameDefaults(), that.getInlineSchemaNameDefaults()) &&
|
Objects.equals(getInlineSchemaNameDefaults(), that.getInlineSchemaNameDefaults()) &&
|
||||||
|
Objects.equals(getOpenAPINormalizer(), that.getOpenAPINormalizer()) &&
|
||||||
Objects.equals(getLanguageSpecificPrimitives(), that.getLanguageSpecificPrimitives()) &&
|
Objects.equals(getLanguageSpecificPrimitives(), that.getLanguageSpecificPrimitives()) &&
|
||||||
Objects.equals(getReservedWordsMappings(), that.getReservedWordsMappings()) &&
|
Objects.equals(getReservedWordsMappings(), that.getReservedWordsMappings()) &&
|
||||||
Objects.equals(getGitHost(), that.getGitHost()) &&
|
Objects.equals(getGitHost(), that.getGitHost()) &&
|
||||||
@ -1116,6 +1160,7 @@ public final class GeneratorSettings implements Serializable {
|
|||||||
getSchemaMappings(),
|
getSchemaMappings(),
|
||||||
getInlineSchemaNameMappings(),
|
getInlineSchemaNameMappings(),
|
||||||
getInlineSchemaNameDefaults(),
|
getInlineSchemaNameDefaults(),
|
||||||
|
getOpenAPINormalizer(),
|
||||||
getLanguageSpecificPrimitives(),
|
getLanguageSpecificPrimitives(),
|
||||||
getReservedWordsMappings(),
|
getReservedWordsMappings(),
|
||||||
getGitHost(),
|
getGitHost(),
|
||||||
|
@ -118,6 +118,7 @@ class OpenApiGeneratorPlugin : Plugin<Project> {
|
|||||||
schemaMappings.set(generate.schemaMappings)
|
schemaMappings.set(generate.schemaMappings)
|
||||||
inlineSchemaNameMappings.set(generate.inlineSchemaNameMappings)
|
inlineSchemaNameMappings.set(generate.inlineSchemaNameMappings)
|
||||||
inlineSchemaNameDefaults.set(generate.inlineSchemaNameDefaults)
|
inlineSchemaNameDefaults.set(generate.inlineSchemaNameDefaults)
|
||||||
|
openapiNormalizer.set(generate.openapiNormalizer)
|
||||||
invokerPackage.set(generate.invokerPackage)
|
invokerPackage.set(generate.invokerPackage)
|
||||||
groupId.set(generate.groupId)
|
groupId.set(generate.groupId)
|
||||||
id.set(generate.id)
|
id.set(generate.id)
|
||||||
|
@ -162,6 +162,11 @@ open class OpenApiGeneratorGenerateExtension(project: Project) {
|
|||||||
*/
|
*/
|
||||||
val inlineSchemaNameDefaults = project.objects.mapProperty<String, String>()
|
val inlineSchemaNameDefaults = project.objects.mapProperty<String, String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies mappings (rules) in OpenAPI normalizer
|
||||||
|
*/
|
||||||
|
val openapiNormalizer = project.objects.mapProperty<String, String>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Root package for generated code.
|
* Root package for generated code.
|
||||||
*/
|
*/
|
||||||
|
@ -250,6 +250,13 @@ open class GenerateTask : DefaultTask() {
|
|||||||
@Input
|
@Input
|
||||||
val inlineSchemaNameDefaults = project.objects.mapProperty<String, String>()
|
val inlineSchemaNameDefaults = project.objects.mapProperty<String, String>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies mappings (rules) in OpenAPI normalizer
|
||||||
|
*/
|
||||||
|
@Optional
|
||||||
|
@Input
|
||||||
|
val openapiNormalizer = project.objects.mapProperty<String, String>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Root package for generated code.
|
* Root package for generated code.
|
||||||
*/
|
*/
|
||||||
@ -758,6 +765,12 @@ open class GenerateTask : DefaultTask() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (openapiNormalizer.isPresent) {
|
||||||
|
openapiNormalizer.get().forEach { entry ->
|
||||||
|
configurator.addOpenAPINormalizer(entry.key, entry.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (typeMappings.isPresent) {
|
if (typeMappings.isPresent) {
|
||||||
typeMappings.get().forEach { entry ->
|
typeMappings.get().forEach { entry ->
|
||||||
configurator.addTypeMapping(entry.key, entry.value)
|
configurator.addTypeMapping(entry.key, entry.value)
|
||||||
|
@ -315,6 +315,12 @@ public class CodeGenMojo extends AbstractMojo {
|
|||||||
@Parameter(name = "inlineSchemaNameDefaults", property = "openapi.generator.maven.plugin.inlineSchemaNameDefaults")
|
@Parameter(name = "inlineSchemaNameDefaults", property = "openapi.generator.maven.plugin.inlineSchemaNameDefaults")
|
||||||
private List<String> inlineSchemaNameDefaults;
|
private List<String> inlineSchemaNameDefaults;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A set of rules for OpenAPI normalizer
|
||||||
|
*/
|
||||||
|
@Parameter(name = "openapiNormalizer", property = "openapi.generator.maven.plugin.openapiNormalizer")
|
||||||
|
private List<String> openapiNormalizer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A map of swagger spec types and the generated code types to use for them
|
* A map of swagger spec types and the generated code types to use for them
|
||||||
*/
|
*/
|
||||||
@ -700,6 +706,12 @@ public class CodeGenMojo extends AbstractMojo {
|
|||||||
configurator);
|
configurator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Retained for backwards-compatibility with configOptions -> openapi-normalizer
|
||||||
|
if (openapiNormalizer == null && configOptions.containsKey("openapi-normalizer")) {
|
||||||
|
applyOpenAPINormalizerKvp(configOptions.get("openapi-normalizer").toString(),
|
||||||
|
configurator);
|
||||||
|
}
|
||||||
|
|
||||||
// Retained for backwards-compatibility with configOptions -> type-mappings
|
// Retained for backwards-compatibility with configOptions -> type-mappings
|
||||||
if (typeMappings == null && configOptions.containsKey("type-mappings")) {
|
if (typeMappings == null && configOptions.containsKey("type-mappings")) {
|
||||||
applyTypeMappingsKvp(configOptions.get("type-mappings").toString(), configurator);
|
applyTypeMappingsKvp(configOptions.get("type-mappings").toString(), configurator);
|
||||||
@ -753,6 +765,11 @@ public class CodeGenMojo extends AbstractMojo {
|
|||||||
applyInlineSchemaNameDefaultsKvpList(inlineSchemaNameDefaults, configurator);
|
applyInlineSchemaNameDefaultsKvpList(inlineSchemaNameDefaults, configurator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Apply OpenAPI normalizer rules
|
||||||
|
if (openapiNormalizer != null && (configOptions == null || !configOptions.containsKey("openapi-normalizer"))) {
|
||||||
|
applyOpenAPINormalizerKvpList(openapiNormalizer, configurator);
|
||||||
|
}
|
||||||
|
|
||||||
// Apply Type Mappings
|
// Apply Type Mappings
|
||||||
if (typeMappings != null && (configOptions == null || !configOptions.containsKey("type-mappings"))) {
|
if (typeMappings != null && (configOptions == null || !configOptions.containsKey("type-mappings"))) {
|
||||||
applyTypeMappingsKvpList(typeMappings, configurator);
|
applyTypeMappingsKvpList(typeMappings, configurator);
|
||||||
|
@ -147,6 +147,8 @@ public interface CodegenConfig {
|
|||||||
|
|
||||||
Map<String, String> inlineSchemaNameDefault();
|
Map<String, String> inlineSchemaNameDefault();
|
||||||
|
|
||||||
|
Map<String, String> openapiNormalizer();
|
||||||
|
|
||||||
Map<String, String> apiTemplateFiles();
|
Map<String, String> apiTemplateFiles();
|
||||||
|
|
||||||
Map<String, String> modelTemplateFiles();
|
Map<String, String> modelTemplateFiles();
|
||||||
@ -330,4 +332,7 @@ public interface CodegenConfig {
|
|||||||
boolean getUseInlineModelResolver();
|
boolean getUseInlineModelResolver();
|
||||||
|
|
||||||
boolean getAddSuffixToDuplicateOperationNicknames();
|
boolean getAddSuffixToDuplicateOperationNicknames();
|
||||||
|
|
||||||
|
boolean getUseOpenAPINormalizer();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -167,6 +167,8 @@ public class DefaultCodegen implements CodegenConfig {
|
|||||||
protected Map<String, String> inlineSchemaNameMapping = new HashMap<>();
|
protected Map<String, String> inlineSchemaNameMapping = new HashMap<>();
|
||||||
// a map to store the inline schema naming conventions
|
// a map to store the inline schema naming conventions
|
||||||
protected Map<String, String> inlineSchemaNameDefault = new HashMap<>();
|
protected Map<String, String> inlineSchemaNameDefault = new HashMap<>();
|
||||||
|
// a map to store the rules in OpenAPI Normalizer
|
||||||
|
protected Map<String, String> openapiNormalizer = new HashMap<>();
|
||||||
protected String modelPackage = "", apiPackage = "", fileSuffix;
|
protected String modelPackage = "", apiPackage = "", fileSuffix;
|
||||||
protected String modelNamePrefix = "", modelNameSuffix = "";
|
protected String modelNamePrefix = "", modelNameSuffix = "";
|
||||||
protected String apiNamePrefix = "", apiNameSuffix = "Api";
|
protected String apiNamePrefix = "", apiNameSuffix = "Api";
|
||||||
@ -1137,6 +1139,11 @@ public class DefaultCodegen implements CodegenConfig {
|
|||||||
return inlineSchemaNameDefault;
|
return inlineSchemaNameDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> openapiNormalizer() {
|
||||||
|
return openapiNormalizer;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String testPackage() {
|
public String testPackage() {
|
||||||
return testPackage;
|
return testPackage;
|
||||||
@ -7939,6 +7946,9 @@ public class DefaultCodegen implements CodegenConfig {
|
|||||||
@Override
|
@Override
|
||||||
public boolean getUseInlineModelResolver() { return true; }
|
public boolean getUseInlineModelResolver() { return true; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getUseOpenAPINormalizer() { return true; }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A function to convert yaml or json ingested strings like property names
|
A function to convert yaml or json ingested strings like property names
|
||||||
And convert special characters like newline, tab, carriage return
|
And convert special characters like newline, tab, carriage return
|
||||||
|
@ -255,6 +255,12 @@ public class DefaultGenerator implements Generator {
|
|||||||
|
|
||||||
config.processOpts();
|
config.processOpts();
|
||||||
|
|
||||||
|
// normalize the spec
|
||||||
|
if (config.getUseOpenAPINormalizer()) {
|
||||||
|
OpenAPINormalizer openapiNormalizer = new OpenAPINormalizer(openAPI, config.openapiNormalizer());
|
||||||
|
openapiNormalizer.normalize();
|
||||||
|
}
|
||||||
|
|
||||||
// resolve inline models
|
// resolve inline models
|
||||||
if (config.getUseInlineModelResolver()) {
|
if (config.getUseInlineModelResolver()) {
|
||||||
InlineModelResolver inlineModelResolver = new InlineModelResolver();
|
InlineModelResolver inlineModelResolver = new InlineModelResolver();
|
||||||
|
@ -0,0 +1,384 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||||
|
* Copyright 2018 SmartBear Software
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.openapitools.codegen;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.models.*;
|
||||||
|
import io.swagger.v3.oas.models.callbacks.Callback;
|
||||||
|
import io.swagger.v3.oas.models.media.*;
|
||||||
|
import io.swagger.v3.oas.models.parameters.Parameter;
|
||||||
|
import io.swagger.v3.oas.models.parameters.RequestBody;
|
||||||
|
import io.swagger.v3.oas.models.responses.ApiResponse;
|
||||||
|
import io.swagger.v3.oas.models.responses.ApiResponses;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.openapitools.codegen.utils.ModelUtils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class OpenAPINormalizer {
|
||||||
|
private OpenAPI openAPI;
|
||||||
|
private Map<String, String> rules = new HashMap<>();
|
||||||
|
|
||||||
|
final Logger LOGGER = LoggerFactory.getLogger(OpenAPINormalizer.class);
|
||||||
|
|
||||||
|
// ============= a list of rules =============
|
||||||
|
// when set to true, all rules are enabled
|
||||||
|
final String ALL = "ALL";
|
||||||
|
boolean enableAll;
|
||||||
|
|
||||||
|
// when set to true, $ref in allOf is treated as parent so that x-parent: true will be added
|
||||||
|
// to the schema in $ref (if x-parent is not present)
|
||||||
|
final String REF_AS_PARENT_IN_ALLOF = "REF_AS_PARENT_IN_ALLOF";
|
||||||
|
boolean enableRefAsParentInAllOf;
|
||||||
|
|
||||||
|
// ============= end of rules =============
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes OpenAPI Normalizer with a set of rules
|
||||||
|
*
|
||||||
|
* @param openAPI OpenAPI
|
||||||
|
* @param rules a map of rules
|
||||||
|
*/
|
||||||
|
public OpenAPINormalizer(OpenAPI openAPI, Map<String, String> rules) {
|
||||||
|
this.openAPI = openAPI;
|
||||||
|
this.rules = rules;
|
||||||
|
parseRules(rules);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the rules.
|
||||||
|
*
|
||||||
|
* @param rules a map of rules
|
||||||
|
*/
|
||||||
|
public void parseRules(Map<String, String> rules) {
|
||||||
|
if (rules == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("true".equalsIgnoreCase(rules.get(ALL))) {
|
||||||
|
enableAll = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableAll || "true".equalsIgnoreCase(rules.get(REF_AS_PARENT_IN_ALLOF))) {
|
||||||
|
enableRefAsParentInAllOf = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes the OpenAPI input, which may not perfectly conform to
|
||||||
|
* the specification.
|
||||||
|
*/
|
||||||
|
void normalize() {
|
||||||
|
if (rules == null || rules.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.openAPI.getComponents() == null) {
|
||||||
|
this.openAPI.setComponents(new Components());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.openAPI.getComponents().getSchemas() == null) {
|
||||||
|
this.openAPI.getComponents().setSchemas(new HashMap<String, Schema>());
|
||||||
|
}
|
||||||
|
|
||||||
|
normalizePaths();
|
||||||
|
normalizeComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes inline models in Paths
|
||||||
|
*/
|
||||||
|
private void normalizePaths() {
|
||||||
|
Paths paths = openAPI.getPaths();
|
||||||
|
if (paths == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<String, PathItem> pathsEntry : paths.entrySet()) {
|
||||||
|
PathItem path = pathsEntry.getValue();
|
||||||
|
List<Operation> operations = new ArrayList<>(path.readOperations());
|
||||||
|
|
||||||
|
// Include callback operation as well
|
||||||
|
for (Operation operation : path.readOperations()) {
|
||||||
|
Map<String, Callback> callbacks = operation.getCallbacks();
|
||||||
|
if (callbacks != null) {
|
||||||
|
operations.addAll(callbacks.values().stream()
|
||||||
|
.flatMap(callback -> callback.values().stream())
|
||||||
|
.flatMap(pathItem -> pathItem.readOperations().stream())
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Operation operation : operations) {
|
||||||
|
normalizeRequestBody(operation);
|
||||||
|
normalizeParameters(operation);
|
||||||
|
normalizeResponses(operation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes schemas in content
|
||||||
|
*
|
||||||
|
* @param content target content
|
||||||
|
*/
|
||||||
|
private void normalizeContent(Content content) {
|
||||||
|
if (content == null || content.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String contentType : content.keySet()) {
|
||||||
|
MediaType mediaType = content.get(contentType);
|
||||||
|
if (mediaType == null) {
|
||||||
|
continue;
|
||||||
|
} else if (mediaType.getSchema() == null) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
normalizeSchema(mediaType.getSchema(), new HashSet<>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes schemas in RequestBody
|
||||||
|
*
|
||||||
|
* @param operation target operation
|
||||||
|
*/
|
||||||
|
private void normalizeRequestBody(Operation operation) {
|
||||||
|
RequestBody requestBody = operation.getRequestBody();
|
||||||
|
if (requestBody == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unalias $ref
|
||||||
|
if (requestBody.get$ref() != null) {
|
||||||
|
String ref = ModelUtils.getSimpleRef(requestBody.get$ref());
|
||||||
|
requestBody = openAPI.getComponents().getRequestBodies().get(ref);
|
||||||
|
|
||||||
|
if (requestBody == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
normalizeContent(requestBody.getContent());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes schemas in parameters
|
||||||
|
*
|
||||||
|
* @param operation target operation
|
||||||
|
*/
|
||||||
|
private void normalizeParameters(Operation operation) {
|
||||||
|
List<Parameter> parameters = operation.getParameters();
|
||||||
|
if (parameters == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Parameter parameter : parameters) {
|
||||||
|
if (parameter.getSchema() == null) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
normalizeSchema(parameter.getSchema(), new HashSet<>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes schemas in ApiResponses
|
||||||
|
*
|
||||||
|
* @param operation target operation
|
||||||
|
*/
|
||||||
|
private void normalizeResponses(Operation operation) {
|
||||||
|
ApiResponses responses = operation.getResponses();
|
||||||
|
if (responses == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<String, ApiResponse> responsesEntry : responses.entrySet()) {
|
||||||
|
if (responsesEntry.getValue() == null) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
normalizeContent(responsesEntry.getValue().getContent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes schemas in components
|
||||||
|
*/
|
||||||
|
private void normalizeComponents() {
|
||||||
|
Map<String, Schema> schemas = openAPI.getComponents().getSchemas();
|
||||||
|
if (schemas == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> schemaNames = new ArrayList<String>(schemas.keySet());
|
||||||
|
for (String schemaName : schemaNames) {
|
||||||
|
Schema schema = schemas.get(schemaName);
|
||||||
|
if (schema == null) {
|
||||||
|
LOGGER.warn("{} not fount found in openapi/components/schemas.", schemaName);
|
||||||
|
} else {
|
||||||
|
normalizeSchema(schema, new HashSet<>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Normalizes a schema
|
||||||
|
*
|
||||||
|
* @param schema Schema
|
||||||
|
* @param visitedSchemas a set of visited schemas
|
||||||
|
*/
|
||||||
|
public void normalizeSchema(Schema schema, Set<Schema> visitedSchemas) {
|
||||||
|
if (schema == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(schema.get$ref())) {
|
||||||
|
// not need to process $ref
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((visitedSchemas.contains(schema))) {
|
||||||
|
return; // skip due to circular reference
|
||||||
|
} else {
|
||||||
|
visitedSchemas.add(schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (schema instanceof ArraySchema) {
|
||||||
|
normalizeSchema(schema.getItems(), visitedSchemas);
|
||||||
|
} else if (schema.getAdditionalProperties() instanceof Schema) { // map
|
||||||
|
normalizeSchema((Schema) schema.getAdditionalProperties(), visitedSchemas);
|
||||||
|
} else if (ModelUtils.isComposedSchema(schema)) {
|
||||||
|
ComposedSchema m = (ComposedSchema) schema;
|
||||||
|
if (m.getAllOf() != null && !m.getAllOf().isEmpty()) {
|
||||||
|
normalizeAllOf(m, visitedSchemas);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m.getOneOf() != null && !m.getOneOf().isEmpty()) {
|
||||||
|
normalizeOneOf(m, visitedSchemas);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m.getAnyOf() != null && !m.getAnyOf().isEmpty()) {
|
||||||
|
normalizeAnyOf(m, visitedSchemas);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m.getProperties() != null && !m.getProperties().isEmpty()) {
|
||||||
|
normalizeProperties(m.getProperties(), visitedSchemas);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m.getAdditionalProperties() != null) {
|
||||||
|
// normalizeAdditionalProperties(m);
|
||||||
|
}
|
||||||
|
} else if (schema.getNot() != null) {// not schema
|
||||||
|
normalizeSchema(schema.getNot(), visitedSchemas);
|
||||||
|
} else if (schema.getProperties() != null && !schema.getProperties().isEmpty()) {
|
||||||
|
normalizeProperties(schema.getProperties(), visitedSchemas);
|
||||||
|
} else if (schema instanceof Schema) {
|
||||||
|
normalizeNonComposedSchema(schema, visitedSchemas);
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Unknown schema type found in normalizer: " + schema);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void normalizeNonComposedSchema(Schema schema, Set<Schema> visitedSchemas) {
|
||||||
|
// normalize non-composed schema (e.g. schema with only properties)
|
||||||
|
}
|
||||||
|
|
||||||
|
private void normalizeProperties(Map<String, Schema> properties, Set<Schema> visitedSchemas) {
|
||||||
|
if (properties == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, Schema> propertiesEntry : properties.entrySet()) {
|
||||||
|
Schema property = propertiesEntry.getValue();
|
||||||
|
normalizeSchema(property, visitedSchemas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void normalizeAllOf(Schema schema, Set<Schema> visitedSchemas) {
|
||||||
|
for (Object item : schema.getAllOf()) {
|
||||||
|
if (!(item instanceof Schema)) {
|
||||||
|
throw new RuntimeException("Error! allOf schema is not of the type Schema: " + item);
|
||||||
|
}
|
||||||
|
// normalize allOf sub schemas one by one
|
||||||
|
normalizeSchema((Schema) item, visitedSchemas);
|
||||||
|
}
|
||||||
|
// process rules here
|
||||||
|
processUseAllOfRefAsParent(schema);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void normalizeOneOf(Schema schema, Set<Schema> visitedSchemas) {
|
||||||
|
for (Object item : schema.getAllOf()) {
|
||||||
|
if (!(item instanceof Schema)) {
|
||||||
|
throw new RuntimeException("Error! allOf schema is not of the type Schema: " + item);
|
||||||
|
}
|
||||||
|
// normalize oenOf sub schemas one by one
|
||||||
|
normalizeSchema((Schema) item, visitedSchemas);
|
||||||
|
}
|
||||||
|
// process rules here
|
||||||
|
}
|
||||||
|
|
||||||
|
private void normalizeAnyOf(Schema schema, Set<Schema> visitedSchemas) {
|
||||||
|
for (Object item : schema.getAllOf()) {
|
||||||
|
if (!(item instanceof Schema)) {
|
||||||
|
throw new RuntimeException("Error! allOf schema is not of the type Schema: " + item);
|
||||||
|
}
|
||||||
|
// normalize anyOf sub schemas one by one
|
||||||
|
normalizeSchema((Schema) item, visitedSchemas);
|
||||||
|
}
|
||||||
|
// process rules here
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================== a list of rules =====================
|
||||||
|
// all rules (fuctions) start with the word "process"
|
||||||
|
private void processUseAllOfRefAsParent(Schema schema) {
|
||||||
|
if (!enableRefAsParentInAllOf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Object item : schema.getAllOf()) {
|
||||||
|
if (!(item instanceof Schema)) {
|
||||||
|
throw new RuntimeException("Error! allOf schema is not of the type Schema: " + item);
|
||||||
|
}
|
||||||
|
Schema s = (Schema) item;
|
||||||
|
|
||||||
|
if (StringUtils.isNotEmpty(s.get$ref())) {
|
||||||
|
String ref = ModelUtils.getSimpleRef(s.get$ref());
|
||||||
|
// TODO need to check for requestBodies?
|
||||||
|
Schema refSchema = openAPI.getComponents().getSchemas().get(ref);
|
||||||
|
if (refSchema == null) {
|
||||||
|
throw new RuntimeException("schema cannot be null with ref " + ref);
|
||||||
|
}
|
||||||
|
if (refSchema.getExtensions() == null) {
|
||||||
|
refSchema.setExtensions(new HashMap<>());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (refSchema.getExtensions().containsKey("x-parent")) {
|
||||||
|
// doing nothing as x-parent already exists
|
||||||
|
} else {
|
||||||
|
refSchema.getExtensions().put("x-parent", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.debug("processUseAllOfRefAsParent added `x-parent: true` to {}", refSchema);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ===================== end of rules =====================
|
||||||
|
}
|
@ -71,6 +71,7 @@ public class CodegenConfigurator {
|
|||||||
private Map<String, String> schemaMappings = new HashMap<>();
|
private Map<String, String> schemaMappings = new HashMap<>();
|
||||||
private Map<String, String> inlineSchemaNameMappings = new HashMap<>();
|
private Map<String, String> inlineSchemaNameMappings = new HashMap<>();
|
||||||
private Map<String, String> inlineSchemaNameDefaults = new HashMap<>();
|
private Map<String, String> inlineSchemaNameDefaults = new HashMap<>();
|
||||||
|
private Map<String, String> openapiNormalizer = new HashMap<>();
|
||||||
private Set<String> languageSpecificPrimitives = new HashSet<>();
|
private Set<String> languageSpecificPrimitives = new HashSet<>();
|
||||||
private Map<String, String> reservedWordsMappings = new HashMap<>();
|
private Map<String, String> reservedWordsMappings = new HashMap<>();
|
||||||
private Map<String, String> serverVariables = new HashMap<>();
|
private Map<String, String> serverVariables = new HashMap<>();
|
||||||
@ -123,6 +124,9 @@ public class CodegenConfigurator {
|
|||||||
if(generatorSettings.getInlineSchemaNameDefaults() != null) {
|
if(generatorSettings.getInlineSchemaNameDefaults() != null) {
|
||||||
configurator.inlineSchemaNameDefaults.putAll(generatorSettings.getInlineSchemaNameDefaults());
|
configurator.inlineSchemaNameDefaults.putAll(generatorSettings.getInlineSchemaNameDefaults());
|
||||||
}
|
}
|
||||||
|
if(generatorSettings.getOpenAPINormalizer() != null) {
|
||||||
|
configurator.openapiNormalizer.putAll(generatorSettings.getOpenAPINormalizer());
|
||||||
|
}
|
||||||
if(generatorSettings.getLanguageSpecificPrimitives() != null) {
|
if(generatorSettings.getLanguageSpecificPrimitives() != null) {
|
||||||
configurator.languageSpecificPrimitives.addAll(generatorSettings.getLanguageSpecificPrimitives());
|
configurator.languageSpecificPrimitives.addAll(generatorSettings.getLanguageSpecificPrimitives());
|
||||||
}
|
}
|
||||||
@ -210,6 +214,12 @@ public class CodegenConfigurator {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CodegenConfigurator addOpenAPINormalizer(String key, String value) {
|
||||||
|
this.openapiNormalizer.put(key, value);
|
||||||
|
generatorSettingsBuilder.withOpenAPINormalizer(key, value);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public CodegenConfigurator addInstantiationType(String key, String value) {
|
public CodegenConfigurator addInstantiationType(String key, String value) {
|
||||||
this.instantiationTypes.put(key, value);
|
this.instantiationTypes.put(key, value);
|
||||||
generatorSettingsBuilder.withInstantiationType(key, value);
|
generatorSettingsBuilder.withInstantiationType(key, value);
|
||||||
@ -382,6 +392,12 @@ public class CodegenConfigurator {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CodegenConfigurator setOpenAPINormalizer(Map<String, String> openapiNormalizer) {
|
||||||
|
this.openapiNormalizer = openapiNormalizer;
|
||||||
|
generatorSettingsBuilder.withOpenAPINormalizer(openapiNormalizer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public CodegenConfigurator setInputSpec(String inputSpec) {
|
public CodegenConfigurator setInputSpec(String inputSpec) {
|
||||||
this.inputSpec = inputSpec;
|
this.inputSpec = inputSpec;
|
||||||
workflowSettingsBuilder.withInputSpec(inputSpec);
|
workflowSettingsBuilder.withInputSpec(inputSpec);
|
||||||
@ -661,6 +677,7 @@ public class CodegenConfigurator {
|
|||||||
config.schemaMapping().putAll(generatorSettings.getSchemaMappings());
|
config.schemaMapping().putAll(generatorSettings.getSchemaMappings());
|
||||||
config.inlineSchemaNameMapping().putAll(generatorSettings.getInlineSchemaNameMappings());
|
config.inlineSchemaNameMapping().putAll(generatorSettings.getInlineSchemaNameMappings());
|
||||||
config.inlineSchemaNameDefault().putAll(generatorSettings.getInlineSchemaNameDefaults());
|
config.inlineSchemaNameDefault().putAll(generatorSettings.getInlineSchemaNameDefaults());
|
||||||
|
config.openapiNormalizer().putAll(generatorSettings.getOpenAPINormalizer());
|
||||||
config.languageSpecificPrimitives().addAll(generatorSettings.getLanguageSpecificPrimitives());
|
config.languageSpecificPrimitives().addAll(generatorSettings.getLanguageSpecificPrimitives());
|
||||||
config.reservedWordsMappings().putAll(generatorSettings.getReservedWordsMappings());
|
config.reservedWordsMappings().putAll(generatorSettings.getReservedWordsMappings());
|
||||||
config.additionalProperties().putAll(generatorSettings.getAdditionalProperties());
|
config.additionalProperties().putAll(generatorSettings.getAdditionalProperties());
|
||||||
|
@ -120,6 +120,19 @@ public final class CodegenConfiguratorUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void applyOpenAPINormalizerKvpList(List<String> openapiNormalizer, CodegenConfigurator configurator) {
|
||||||
|
for (String propString : openapiNormalizer) {
|
||||||
|
applyOpenAPINormalizerKvp(propString, configurator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void applyOpenAPINormalizerKvp(String openapiNormalizer, CodegenConfigurator configurator) {
|
||||||
|
final Map<String, String> map = createMapFromKeyValuePairs(openapiNormalizer);
|
||||||
|
for (Map.Entry<String, String> entry : map.entrySet()) {
|
||||||
|
configurator.addOpenAPINormalizer(entry.getKey().trim(), entry.getValue().trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void applyTypeMappingsKvpList(List<String> typeMappings, CodegenConfigurator configurator) {
|
public static void applyTypeMappingsKvpList(List<String> typeMappings, CodegenConfigurator configurator) {
|
||||||
for (String propString : typeMappings) {
|
for (String propString : typeMappings) {
|
||||||
applyTypeMappingsKvp(propString, configurator);
|
applyTypeMappingsKvp(propString, configurator);
|
||||||
|
@ -308,15 +308,15 @@ public class ModelUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoke the specified visitor function for every schema that matches mimeType in the OpenAPI document.
|
* Invoke the specified visitor function for every schema that matches mimeType in the OpenAPI document.
|
||||||
*
|
* <p>
|
||||||
* To avoid infinite recursion, referenced schemas are visited only once. When a referenced schema is visited,
|
* To avoid infinite recursion, referenced schemas are visited only once. When a referenced schema is visited,
|
||||||
* it is added to visitedSchemas.
|
* it is added to visitedSchemas.
|
||||||
*
|
*
|
||||||
* @param openAPI the OpenAPI document that contains schema objects.
|
* @param openAPI the OpenAPI document that contains schema objects.
|
||||||
* @param schema the root schema object to be visited.
|
* @param schema the root schema object to be visited.
|
||||||
* @param mimeType the mime type. TODO: does not seem to be used in a meaningful way.
|
* @param mimeType the mime type. TODO: does not seem to be used in a meaningful way.
|
||||||
* @param visitedSchemas the list of referenced schemas that have been visited.
|
* @param visitedSchemas the list of referenced schemas that have been visited.
|
||||||
* @param visitor the visitor function which is invoked for every visited schema.
|
* @param visitor the visitor function which is invoked for every visited schema.
|
||||||
*/
|
*/
|
||||||
private static void visitSchema(OpenAPI openAPI, Schema schema, String mimeType, List<String> visitedSchemas, OpenAPISchemaVisitor visitor) {
|
private static void visitSchema(OpenAPI openAPI, Schema schema, String mimeType, List<String> visitedSchemas, OpenAPISchemaVisitor visitor) {
|
||||||
visitor.visit(schema, mimeType);
|
visitor.visit(schema, mimeType);
|
||||||
@ -425,13 +425,14 @@ public class ModelUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the specified schema is an object with a fixed number of properties.
|
* Return true if the specified schema is an object with a fixed number of properties.
|
||||||
*
|
* <p>
|
||||||
* A ObjectSchema differs from a MapSchema in the following way:
|
* A ObjectSchema differs from a MapSchema in the following way:
|
||||||
* - An ObjectSchema is not extensible, i.e. it has a fixed number of properties.
|
* - An ObjectSchema is not extensible, i.e. it has a fixed number of properties.
|
||||||
* - A MapSchema is an object that can be extended with an arbitrary set of properties.
|
* - A MapSchema is an object that can be extended with an arbitrary set of properties.
|
||||||
* The payload may include dynamic properties.
|
* The payload may include dynamic properties.
|
||||||
*
|
* <p>
|
||||||
* For example, an OpenAPI schema is considered an ObjectSchema in the following scenarios:
|
* For example, an OpenAPI schema is considered an ObjectSchema in the following scenarios:
|
||||||
|
* <p>
|
||||||
*
|
*
|
||||||
* type: object
|
* type: object
|
||||||
* additionalProperties: false
|
* additionalProperties: false
|
||||||
@ -479,16 +480,17 @@ public class ModelUtils {
|
|||||||
* Return true if the specified 'schema' is an object that can be extended with additional properties.
|
* Return true if the specified 'schema' is an object that can be extended with additional properties.
|
||||||
* Additional properties means a Schema should support all explicitly defined properties plus any
|
* Additional properties means a Schema should support all explicitly defined properties plus any
|
||||||
* undeclared properties.
|
* undeclared properties.
|
||||||
*
|
* <p>
|
||||||
* A MapSchema differs from an ObjectSchema in the following way:
|
* A MapSchema differs from an ObjectSchema in the following way:
|
||||||
* - An ObjectSchema is not extensible, i.e. it has a fixed number of properties.
|
* - An ObjectSchema is not extensible, i.e. it has a fixed number of properties.
|
||||||
* - A MapSchema is an object that can be extended with an arbitrary set of properties.
|
* - A MapSchema is an object that can be extended with an arbitrary set of properties.
|
||||||
* The payload may include dynamic properties.
|
* The payload may include dynamic properties.
|
||||||
*
|
* <p>
|
||||||
* Note that isMapSchema returns true for a composed schema (allOf, anyOf, oneOf) that also defines
|
* Note that isMapSchema returns true for a composed schema (allOf, anyOf, oneOf) that also defines
|
||||||
* additionalproperties.
|
* additionalproperties.
|
||||||
*
|
* <p>
|
||||||
* For example, an OpenAPI schema is considered a MapSchema in the following scenarios:
|
* For example, an OpenAPI schema is considered a MapSchema in the following scenarios:
|
||||||
|
* <p>
|
||||||
*
|
*
|
||||||
* type: object
|
* type: object
|
||||||
* additionalProperties: true
|
* additionalProperties: true
|
||||||
@ -772,14 +774,14 @@ public class ModelUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if the schema is a free form object.
|
* Check to see if the schema is a free form object.
|
||||||
*
|
* <p>
|
||||||
* A free form object is an object (i.e. 'type: object' in a OAS document) that:
|
* A free form object is an object (i.e. 'type: object' in a OAS document) that:
|
||||||
* 1) Does not define properties, and
|
* 1) Does not define properties, and
|
||||||
* 2) Is not a composed schema (no anyOf, oneOf, allOf), and
|
* 2) Is not a composed schema (no anyOf, oneOf, allOf), and
|
||||||
* 3) additionalproperties is not defined, or additionalproperties: true, or additionalproperties: {}.
|
* 3) additionalproperties is not defined, or additionalproperties: true, or additionalproperties: {}.
|
||||||
*
|
* <p>
|
||||||
* Examples:
|
* Examples:
|
||||||
*
|
* <p>
|
||||||
* components:
|
* components:
|
||||||
* schemas:
|
* schemas:
|
||||||
* arbitraryObject:
|
* arbitraryObject:
|
||||||
@ -798,7 +800,7 @@ public class ModelUtils {
|
|||||||
* The value can be any type except the 'null' value.
|
* The value can be any type except the 'null' value.
|
||||||
*
|
*
|
||||||
* @param openAPI the object that encapsulates the OAS document.
|
* @param openAPI the object that encapsulates the OAS document.
|
||||||
* @param schema potentially containing a '$ref'
|
* @param schema potentially containing a '$ref'
|
||||||
* @return true if it's a free-form object
|
* @return true if it's a free-form object
|
||||||
*/
|
*/
|
||||||
public static boolean isFreeFormObject(OpenAPI openAPI, Schema schema) {
|
public static boolean isFreeFormObject(OpenAPI openAPI, Schema schema) {
|
||||||
@ -1054,10 +1056,10 @@ public class ModelUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the first Schema from a specified OAS 'content' section.
|
* Return the first Schema from a specified OAS 'content' section.
|
||||||
*
|
* <p>
|
||||||
* For example, given the following OAS, this method returns the schema
|
* For example, given the following OAS, this method returns the schema
|
||||||
* for the 'application/json' content type because it is listed first in the OAS.
|
* for the 'application/json' content type because it is listed first in the OAS.
|
||||||
*
|
* <p>
|
||||||
* responses:
|
* responses:
|
||||||
* '200':
|
* '200':
|
||||||
* content:
|
* content:
|
||||||
@ -1099,8 +1101,8 @@ public class ModelUtils {
|
|||||||
/**
|
/**
|
||||||
* Has self reference?
|
* Has self reference?
|
||||||
*
|
*
|
||||||
* @param openAPI OpenAPI spec.
|
* @param openAPI OpenAPI spec.
|
||||||
* @param schema Schema
|
* @param schema Schema
|
||||||
* @param visitedSchemaNames A set of visited schema names
|
* @param visitedSchemaNames A set of visited schema names
|
||||||
* @return boolean true if it has at least one self reference
|
* @return boolean true if it has at least one self reference
|
||||||
*/
|
*/
|
||||||
@ -1257,7 +1259,7 @@ public class ModelUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the additionalProperties Schema for the specified input schema.
|
* Returns the additionalProperties Schema for the specified input schema.
|
||||||
*
|
* <p>
|
||||||
* The additionalProperties keyword is used to control the handling of additional, undeclared
|
* The additionalProperties keyword is used to control the handling of additional, undeclared
|
||||||
* properties, that is, properties whose names are not listed in the properties keyword.
|
* properties, that is, properties whose names are not listed in the properties keyword.
|
||||||
* The additionalProperties keyword may be either a boolean or an object.
|
* The additionalProperties keyword may be either a boolean or an object.
|
||||||
@ -1267,9 +1269,9 @@ public class ModelUtils {
|
|||||||
* to the boolean value True or setting additionalProperties: {}
|
* to the boolean value True or setting additionalProperties: {}
|
||||||
*
|
*
|
||||||
* @param openAPI the object that encapsulates the OAS document.
|
* @param openAPI the object that encapsulates the OAS document.
|
||||||
* @param schema the input schema that may or may not have the additionalProperties keyword.
|
* @param schema the input schema that may or may not have the additionalProperties keyword.
|
||||||
* @return the Schema of the additionalProperties. The null value is returned if no additional
|
* @return the Schema of the additionalProperties. The null value is returned if no additional
|
||||||
* properties are allowed.
|
* properties are allowed.
|
||||||
*/
|
*/
|
||||||
public static Schema getAdditionalProperties(OpenAPI openAPI, Schema schema) {
|
public static Schema getAdditionalProperties(OpenAPI openAPI, Schema schema) {
|
||||||
Object addProps = schema.getAdditionalProperties();
|
Object addProps = schema.getAdditionalProperties();
|
||||||
@ -1380,10 +1382,10 @@ public class ModelUtils {
|
|||||||
* that specify a determinator.
|
* that specify a determinator.
|
||||||
* If there are multiple elements in the composed schema and it is not clear
|
* If there are multiple elements in the composed schema and it is not clear
|
||||||
* which one should be the parent, return null.
|
* which one should be the parent, return null.
|
||||||
*
|
* <p>
|
||||||
* For example, given the following OAS spec, the parent of 'Dog' is Animal
|
* For example, given the following OAS spec, the parent of 'Dog' is Animal
|
||||||
* because 'Animal' specifies a discriminator.
|
* because 'Animal' specifies a discriminator.
|
||||||
*
|
* <p>
|
||||||
* animal:
|
* animal:
|
||||||
* type: object
|
* type: object
|
||||||
* discriminator:
|
* discriminator:
|
||||||
@ -1391,6 +1393,7 @@ public class ModelUtils {
|
|||||||
* properties:
|
* properties:
|
||||||
* type: string
|
* type: string
|
||||||
*
|
*
|
||||||
|
* <p>
|
||||||
* dog:
|
* dog:
|
||||||
* allOf:
|
* allOf:
|
||||||
* - $ref: '#/components/schemas/animal'
|
* - $ref: '#/components/schemas/animal'
|
||||||
@ -1418,10 +1421,10 @@ public class ModelUtils {
|
|||||||
LOGGER.error("Failed to obtain schema from {}", parentName);
|
LOGGER.error("Failed to obtain schema from {}", parentName);
|
||||||
return "UNKNOWN_PARENT_NAME";
|
return "UNKNOWN_PARENT_NAME";
|
||||||
} else if (hasOrInheritsDiscriminator(s, allSchemas)) {
|
} else if (hasOrInheritsDiscriminator(s, allSchemas)) {
|
||||||
// discriminator.propertyName is used
|
// discriminator.propertyName is used or x-parent is used
|
||||||
return parentName;
|
return parentName;
|
||||||
} else {
|
} else {
|
||||||
// not a parent since discriminator.propertyName is not set
|
// not a parent since discriminator.propertyName or x-parent is not set
|
||||||
hasAmbiguousParents = true;
|
hasAmbiguousParents = true;
|
||||||
refedWithoutDiscriminator.add(parentName);
|
refedWithoutDiscriminator.add(parentName);
|
||||||
}
|
}
|
||||||
@ -1476,7 +1479,7 @@ public class ModelUtils {
|
|||||||
LOGGER.error("Failed to obtain schema from {}", parentName);
|
LOGGER.error("Failed to obtain schema from {}", parentName);
|
||||||
names.add("UNKNOWN_PARENT_NAME");
|
names.add("UNKNOWN_PARENT_NAME");
|
||||||
} else if (hasOrInheritsDiscriminator(s, allSchemas)) {
|
} else if (hasOrInheritsDiscriminator(s, allSchemas)) {
|
||||||
// discriminator.propertyName is used
|
// discriminator.propertyName is used or x-parent is used
|
||||||
names.add(parentName);
|
names.add(parentName);
|
||||||
if (includeAncestors && s instanceof ComposedSchema) {
|
if (includeAncestors && s instanceof ComposedSchema) {
|
||||||
names.addAll(getAllParentsName((ComposedSchema) s, allSchemas, true));
|
names.addAll(getAllParentsName((ComposedSchema) s, allSchemas, true));
|
||||||
@ -1501,7 +1504,8 @@ public class ModelUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean hasOrInheritsDiscriminator(Schema schema, Map<String, Schema> allSchemas) {
|
private static boolean hasOrInheritsDiscriminator(Schema schema, Map<String, Schema> allSchemas) {
|
||||||
if (schema.getDiscriminator() != null && StringUtils.isNotEmpty(schema.getDiscriminator().getPropertyName())) {
|
if ((schema.getDiscriminator() != null && StringUtils.isNotEmpty(schema.getDiscriminator().getPropertyName()))
|
||||||
|
|| (isExtensionParent(schema))) { // x-parent is used
|
||||||
return true;
|
return true;
|
||||||
} else if (StringUtils.isNotEmpty(schema.get$ref())) {
|
} else if (StringUtils.isNotEmpty(schema.get$ref())) {
|
||||||
String parentName = getSimpleRef(schema.get$ref());
|
String parentName = getSimpleRef(schema.get$ref());
|
||||||
@ -1523,18 +1527,43 @@ public class ModelUtils {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If it's a boolean, returns the value of the extension `x-parent`.
|
||||||
|
* If it's string, return true if it's non-empty.
|
||||||
|
* If the return value is `true`, the schema is a parent.
|
||||||
|
*
|
||||||
|
* @param schema Schema
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static boolean isExtensionParent(Schema schema) {
|
||||||
|
if (schema.getExtensions() == null) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
Object xParent = schema.getExtensions().get("x-parent");
|
||||||
|
if (xParent == null) {
|
||||||
|
return false;
|
||||||
|
} else if (xParent instanceof Boolean) {
|
||||||
|
return (Boolean) xParent;
|
||||||
|
} else if (xParent instanceof String) {
|
||||||
|
return StringUtils.isNotEmpty((String) xParent);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the 'nullable' attribute is set to true in the schema, i.e. if the value
|
* Return true if the 'nullable' attribute is set to true in the schema, i.e. if the value
|
||||||
* of the property can be the null value.
|
* of the property can be the null value.
|
||||||
*
|
* <p>
|
||||||
* In addition, if the OAS document is 3.1 or above, isNullable returns true if the input
|
* In addition, if the OAS document is 3.1 or above, isNullable returns true if the input
|
||||||
* schema is a 'oneOf' composed document with at most two children, and one of the children
|
* schema is a 'oneOf' composed document with at most two children, and one of the children
|
||||||
* is the 'null' type.
|
* is the 'null' type.
|
||||||
*
|
* <p>
|
||||||
* The caller is responsible for resolving schema references before invoking isNullable.
|
* The caller is responsible for resolving schema references before invoking isNullable.
|
||||||
* If the input schema is a $ref and the referenced schema has 'nullable: true', this method
|
* If the input schema is a $ref and the referenced schema has 'nullable: true', this method
|
||||||
* returns false (because the nullable attribute is defined in the referenced schema).
|
* returns false (because the nullable attribute is defined in the referenced schema).
|
||||||
*
|
* <p>
|
||||||
* The 'nullable' attribute was introduced in OAS 3.0.
|
* The 'nullable' attribute was introduced in OAS 3.0.
|
||||||
* The 'nullable' attribute is deprecated in OAS 3.1. In a OAS 3.1 document, the preferred way
|
* The 'nullable' attribute is deprecated in OAS 3.1. In a OAS 3.1 document, the preferred way
|
||||||
* to specify nullable properties is to use the 'null' type.
|
* to specify nullable properties is to use the 'null' type.
|
||||||
@ -1564,11 +1593,11 @@ public class ModelUtils {
|
|||||||
/**
|
/**
|
||||||
* Return true if the specified composed schema is 'oneOf', contains one or two elements,
|
* Return true if the specified composed schema is 'oneOf', contains one or two elements,
|
||||||
* and at least one of the elements is the 'null' type.
|
* and at least one of the elements is the 'null' type.
|
||||||
*
|
* <p>
|
||||||
* The 'null' type is supported in OAS 3.1 and above.
|
* The 'null' type is supported in OAS 3.1 and above.
|
||||||
* In the example below, the 'OptionalOrder' can have the null value because the 'null'
|
* In the example below, the 'OptionalOrder' can have the null value because the 'null'
|
||||||
* type is one of the elements under 'oneOf'.
|
* type is one of the elements under 'oneOf'.
|
||||||
*
|
* <p>
|
||||||
* OptionalOrder:
|
* OptionalOrder:
|
||||||
* oneOf:
|
* oneOf:
|
||||||
* - type: 'null'
|
* - type: 'null'
|
||||||
@ -1591,13 +1620,13 @@ public class ModelUtils {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* isNullType returns true if the input schema is the 'null' type.
|
* isNullType returns true if the input schema is the 'null' type.
|
||||||
*
|
* <p>
|
||||||
* The 'null' type is supported in OAS 3.1 and above. It is not supported
|
* The 'null' type is supported in OAS 3.1 and above. It is not supported
|
||||||
* in OAS 2.0 and OAS 3.0.x.
|
* in OAS 2.0 and OAS 3.0.x.
|
||||||
*
|
* <p>
|
||||||
* For example, the "null" type could be used to specify that a value must
|
* For example, the "null" type could be used to specify that a value must
|
||||||
* either be null or a specified type:
|
* either be null or a specified type:
|
||||||
*
|
* <p>
|
||||||
* OptionalOrder:
|
* OptionalOrder:
|
||||||
* oneOf:
|
* oneOf:
|
||||||
* - type: 'null'
|
* - type: 'null'
|
||||||
@ -1617,6 +1646,7 @@ public class ModelUtils {
|
|||||||
* For when a type is not defined on a schema
|
* For when a type is not defined on a schema
|
||||||
* Note: properties, additionalProperties, enums, validations, items, and composed schemas (oneOf/anyOf/allOf)
|
* Note: properties, additionalProperties, enums, validations, items, and composed schemas (oneOf/anyOf/allOf)
|
||||||
* can be defined or omitted on these any type schemas
|
* can be defined or omitted on these any type schemas
|
||||||
|
*
|
||||||
* @param schema the schema that we are checking
|
* @param schema the schema that we are checking
|
||||||
* @return boolean
|
* @return boolean
|
||||||
*/
|
*/
|
||||||
@ -1713,7 +1743,7 @@ public class ModelUtils {
|
|||||||
|
|
||||||
private static ObjectMapper getRightMapper(String data) {
|
private static ObjectMapper getRightMapper(String data) {
|
||||||
ObjectMapper mapper;
|
ObjectMapper mapper;
|
||||||
if (data.trim().startsWith("{")) {
|
if (data.trim().startsWith("{")) {
|
||||||
mapper = JSON_MAPPER;
|
mapper = JSON_MAPPER;
|
||||||
} else {
|
} else {
|
||||||
mapper = YAML_MAPPER;
|
mapper = YAML_MAPPER;
|
||||||
@ -1725,11 +1755,9 @@ public class ModelUtils {
|
|||||||
* Parse and return a JsonNode representation of the input OAS document.
|
* Parse and return a JsonNode representation of the input OAS document.
|
||||||
*
|
*
|
||||||
* @param location the URL of the OAS document.
|
* @param location the URL of the OAS document.
|
||||||
* @param auths the list of authorization values to access the remote URL.
|
* @param auths the list of authorization values to access the remote URL.
|
||||||
*
|
|
||||||
* @throws java.lang.Exception if an error occurs while retrieving the OpenAPI document.
|
|
||||||
*
|
|
||||||
* @return A JsonNode representation of the input OAS document.
|
* @return A JsonNode representation of the input OAS document.
|
||||||
|
* @throws java.lang.Exception if an error occurs while retrieving the OpenAPI document.
|
||||||
*/
|
*/
|
||||||
public static JsonNode readWithInfo(String location, List<AuthorizationValue> auths) throws Exception {
|
public static JsonNode readWithInfo(String location, List<AuthorizationValue> auths) throws Exception {
|
||||||
String data;
|
String data;
|
||||||
@ -1756,14 +1784,13 @@ public class ModelUtils {
|
|||||||
/**
|
/**
|
||||||
* Parse the OAS document at the specified location, get the swagger or openapi version
|
* Parse the OAS document at the specified location, get the swagger or openapi version
|
||||||
* as specified in the source document, and return the version.
|
* as specified in the source document, and return the version.
|
||||||
*
|
* <p>
|
||||||
* For OAS 2.0 documents, return the value of the 'swagger' attribute.
|
* For OAS 2.0 documents, return the value of the 'swagger' attribute.
|
||||||
* For OAS 3.x documents, return the value of the 'openapi' attribute.
|
* For OAS 3.x documents, return the value of the 'openapi' attribute.
|
||||||
*
|
*
|
||||||
* @param openAPI the object that encapsulates the OAS document.
|
* @param openAPI the object that encapsulates the OAS document.
|
||||||
* @param location the URL of the OAS document.
|
* @param location the URL of the OAS document.
|
||||||
* @param auths the list of authorization values to access the remote URL.
|
* @param auths the list of authorization values to access the remote URL.
|
||||||
*
|
|
||||||
* @return the version of the OpenAPI document.
|
* @return the version of the OpenAPI document.
|
||||||
*/
|
*/
|
||||||
public static SemVer getOpenApiVersion(OpenAPI openAPI, String location, List<AuthorizationValue> auths) {
|
public static SemVer getOpenApiVersion(OpenAPI openAPI, String location, List<AuthorizationValue> auths) {
|
||||||
|
@ -56,7 +56,6 @@ import java.util.stream.Collectors;
|
|||||||
|
|
||||||
import static org.testng.Assert.*;
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
|
|
||||||
public class DefaultCodegenTest {
|
public class DefaultCodegenTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -4300,4 +4299,29 @@ public class DefaultCodegenTest {
|
|||||||
Assert.assertFalse(inlineEnumSchemaProperty.isContainer);
|
Assert.assertFalse(inlineEnumSchemaProperty.isContainer);
|
||||||
Assert.assertFalse(inlineEnumSchemaProperty.isPrimitiveType);
|
Assert.assertFalse(inlineEnumSchemaProperty.isPrimitiveType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOpenAPINormalizer() {
|
||||||
|
OpenAPI openAPI = TestUtils.parseSpec("src/test/resources/3_0/allOf_extension_parent.yaml");
|
||||||
|
|
||||||
|
Schema schema = openAPI.getComponents().getSchemas().get("AnotherPerson");
|
||||||
|
assertNull(schema.getExtensions());
|
||||||
|
|
||||||
|
Schema schema2 = openAPI.getComponents().getSchemas().get("Person");
|
||||||
|
assertEquals(schema2.getExtensions().get("x-parent"), "abstract");
|
||||||
|
|
||||||
|
Map<String, String> options = new HashMap<>();
|
||||||
|
options.put("REF_AS_PARENT_IN_ALLOF", "true");
|
||||||
|
OpenAPINormalizer openAPINormalizer = new OpenAPINormalizer(openAPI, options);
|
||||||
|
openAPINormalizer.normalize();
|
||||||
|
|
||||||
|
Schema schema3 = openAPI.getComponents().getSchemas().get("AnotherPerson");
|
||||||
|
assertEquals(schema3.getExtensions().get("x-parent"), true);
|
||||||
|
|
||||||
|
Schema schema4 = openAPI.getComponents().getSchemas().get("AnotherParent");
|
||||||
|
assertEquals(schema4.getExtensions().get("x-parent"), true);
|
||||||
|
|
||||||
|
Schema schema5 = openAPI.getComponents().getSchemas().get("Person");
|
||||||
|
assertEquals(schema5.getExtensions().get("x-parent"), "abstract");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1717,4 +1717,39 @@ public class JavaClientCodegenTest {
|
|||||||
"localVarQueryParams.addAll(ApiClient.parameterToPairs(\"multi\", \"values\", queryObject.getValues()));"
|
"localVarQueryParams.addAll(ApiClient.parameterToPairs(\"multi\", \"values\", queryObject.getValues()));"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testJdkHttpClientWithAndWithoutParentExtension() throws Exception {
|
||||||
|
Map<String, Object> properties = new HashMap<>();
|
||||||
|
properties.put(CodegenConstants.API_PACKAGE, "xyz.abcdef.api");
|
||||||
|
properties.put(CodegenConstants.MODEL_PACKAGE, "xyz.abcdef.model");
|
||||||
|
properties.put(CodegenConstants.INVOKER_PACKAGE, "xyz.abcdef.invoker");
|
||||||
|
|
||||||
|
File output = Files.createTempDirectory("test").toFile();
|
||||||
|
output.deleteOnExit();
|
||||||
|
|
||||||
|
final CodegenConfigurator configurator = new CodegenConfigurator()
|
||||||
|
.setGeneratorName("java")
|
||||||
|
// use default `okhttp-gson`
|
||||||
|
//.setLibrary(JavaClientCodegen.NATIVE)
|
||||||
|
.setAdditionalProperties(properties)
|
||||||
|
.setInputSpec("src/test/resources/3_0/allOf_extension_parent.yaml")
|
||||||
|
.setOutputDir(output.getAbsolutePath().replace("\\", "/"));
|
||||||
|
|
||||||
|
final ClientOptInput clientOptInput = configurator.toClientOptInput();
|
||||||
|
DefaultGenerator generator = new DefaultGenerator();
|
||||||
|
generator.setGeneratorPropertyDefault(CodegenConstants.MODELS, "true");
|
||||||
|
generator.setGeneratorPropertyDefault(CodegenConstants.APIS, "true");
|
||||||
|
List<File> files = generator.opts(clientOptInput).generate();
|
||||||
|
|
||||||
|
Assert.assertEquals(files.size(), 30);
|
||||||
|
validateJavaSourceFiles(files);
|
||||||
|
|
||||||
|
TestUtils.assertFileContains(Paths.get(output + "/src/main/java/xyz/abcdef/model/Child.java"),
|
||||||
|
"public class Child extends Person {");
|
||||||
|
TestUtils.assertFileContains(Paths.get(output + "/src/main/java/xyz/abcdef/model/Adult.java"),
|
||||||
|
"public class Adult extends Person {");
|
||||||
|
TestUtils.assertFileContains(Paths.get(output + "/src/main/java/xyz/abcdef/model/AnotherChild.java"),
|
||||||
|
"public class AnotherChild {");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
openapi: 3.0.1
|
||||||
|
info:
|
||||||
|
version: 1.0.0
|
||||||
|
title: Example
|
||||||
|
license:
|
||||||
|
name: MIT
|
||||||
|
servers:
|
||||||
|
- url: http://api.example.xyz/v1
|
||||||
|
paths:
|
||||||
|
/person/display/{personId}:
|
||||||
|
get:
|
||||||
|
parameters:
|
||||||
|
- name: personId
|
||||||
|
in: path
|
||||||
|
required: true
|
||||||
|
description: The id of the person to retrieve
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
operationId: list
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/Person"
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Person:
|
||||||
|
description: person using x-parent (abstract) to indicate it's a parent class
|
||||||
|
type: object
|
||||||
|
x-parent: "abstract"
|
||||||
|
properties:
|
||||||
|
$_type:
|
||||||
|
type: string
|
||||||
|
lastName:
|
||||||
|
type: string
|
||||||
|
firstName:
|
||||||
|
type: string
|
||||||
|
Adult:
|
||||||
|
description: A representation of an adult
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/Person'
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
children:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: "#/components/schemas/Child"
|
||||||
|
Child:
|
||||||
|
description: A representation of a child
|
||||||
|
allOf:
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
age:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
- $ref: '#/components/schemas/Person'
|
||||||
|
AnotherChild:
|
||||||
|
description: another child class that does NOT extend/inherit AnotherPerson
|
||||||
|
allOf:
|
||||||
|
- type: object
|
||||||
|
properties:
|
||||||
|
age:
|
||||||
|
type: integer
|
||||||
|
format: int32
|
||||||
|
- $ref: '#/components/schemas/AnotherPerson'
|
||||||
|
AnotherPerson:
|
||||||
|
description: person object without x-parent extension
|
||||||
|
type: object
|
||||||
|
allOf:
|
||||||
|
- properties:
|
||||||
|
$_type:
|
||||||
|
type: string
|
||||||
|
lastName:
|
||||||
|
type: string
|
||||||
|
firstName:
|
||||||
|
type: string
|
||||||
|
- $ref: '#/components/schemas/AnotherParent'
|
||||||
|
AnotherParent:
|
||||||
|
description: parent object without x-parent extension
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
isParent:
|
||||||
|
type: boolean
|
||||||
|
mum_or_dad:
|
||||||
|
type: string
|
Loading…
x
Reference in New Issue
Block a user