Skip to content
This repository was archived by the owner on Dec 25, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
import org.openapijsonschematools.codegen.model.CodegenServer;
import org.openapijsonschematools.codegen.model.CodegenTag;
import org.openapijsonschematools.codegen.model.CodegenXml;
import org.openapijsonschematools.codegen.model.EnumInfo;
import org.openapijsonschematools.codegen.model.EnumValue;
import org.openapijsonschematools.codegen.model.LinkedHashMapWithContext;
import org.openapijsonschematools.codegen.model.PairCacheKey;
Expand Down Expand Up @@ -2282,7 +2283,7 @@ public CodegenSchema fromSchema(Schema p, String sourceJsonPath, String currentJ
property.items = fromSchema(
p.getItems(), sourceJsonPath, currentJsonPath + "/items");
}
property.enumValueToName = getEnumValueToName(p, currentJsonPath, sourceJsonPath);
property.enumInfo = getEnumInfo(p, currentJsonPath, sourceJsonPath, property.types);
List<Schema> anyOfs = ((Schema<?>) p).getAnyOf();
if (anyOfs != null && !anyOfs.isEmpty()) {
property.anyOf = getComposedProperties(anyOfs, "anyOf", sourceJsonPath, currentJsonPath);
Expand All @@ -2299,24 +2300,36 @@ public CodegenSchema fromSchema(Schema p, String sourceJsonPath, String currentJ
property.optionalProperties = getOptionalProperties(property.properties, required, sourceJsonPath, currentName);
if ((property.types == null || property.types.contains("object")) && sourceJsonPath != null) {
// only set mapInputJsonPathPiece when object input is possible
if (property.requiredProperties != null && property.optionalProperties == null) {
// only required
property.mapInputJsonPathPiece = property.requiredProperties.jsonPathPiece();
property.mapOutputJsonPathPiece = getKey(currentName + "Dict", "schemaProperty", sourceJsonPath);
} else if (property.requiredProperties == null && property.optionalProperties != null) {
// only optional
property.mapInputJsonPathPiece = property.optionalProperties.jsonPathPiece();
property.mapOutputJsonPathPiece = getKey(currentName + "Dict", "schemaProperty", sourceJsonPath);
} else if (property.requiredProperties != null && property.optionalProperties != null) {
// optional + required
property.mapInputJsonPathPiece = getKey(currentName + "DictInput", "schemaProperty", sourceJsonPath);
property.mapOutputJsonPathPiece = getKey(currentName + "Dict", "schemaProperty", sourceJsonPath);
} else if (property.additionalProperties != null) {
// only addProps
property.mapInputJsonPathPiece = getKey(currentName + "DictInput", "schemaProperty", sourceJsonPath);
// even though the definition is the same, mapOutputJsonPathPiece needs to be different
// so an implementing class can be written
property.mapOutputJsonPathPiece = getKey(currentName + "Dict", "schemaProperty", sourceJsonPath);
boolean requiredPropsExist = property.requiredProperties != null;
boolean optionalPropsExist = property.optionalProperties != null;
String firstBoolChar = requiredPropsExist? "1" : "0";
String SecondBoolChar = optionalPropsExist? "1" : "0";
String boolState = firstBoolChar + SecondBoolChar;
switch (boolState) {
case "00":
if (property.additionalProperties != null) {
// only addProps
property.mapInputJsonPathPiece = getKey(currentName + "DictInput", "schemaProperty", sourceJsonPath);
// even though the definition is the same, mapOutputJsonPathPiece needs to be different
// so an implementing class can be written
property.mapOutputJsonPathPiece = getKey(currentName + "Dict", "schemaProperty", sourceJsonPath);
}
break;
case "11":
// optional + required
property.mapInputJsonPathPiece = getKey(currentName + "DictInput", "schemaProperty", sourceJsonPath);
property.mapOutputJsonPathPiece = getKey(currentName + "Dict", "schemaProperty", sourceJsonPath);
break;
case "10":
// only required
property.mapInputJsonPathPiece = property.requiredProperties.jsonPathPiece();
property.mapOutputJsonPathPiece = getKey(currentName + "Dict", "schemaProperty", sourceJsonPath);
break;
case "01":
// only optional
property.mapInputJsonPathPiece = property.optionalProperties.jsonPathPiece();
property.mapOutputJsonPathPiece = getKey(currentName + "Dict", "schemaProperty", sourceJsonPath);
break;
}
}
if ((property.types == null || property.types.contains("array")) && sourceJsonPath != null && property.items != null) {
Expand Down Expand Up @@ -3479,19 +3492,22 @@ private void updateComponentsFilepath(String[] pathPieces) {
String requestBodiesIdentifier = "request_bodies";
String securitySchemesIdentifier = "security_schemes";
// rename schemas + requestBodies
if (pathPieces[2].equals("schemas")) {
// modelPackage replaces pathPieces[1] + pathPieces[2]
pathPieces[1] = modelPackagePathFragment();
pathPieces[2] = null;
if (pathPieces.length == 4) {
// #/components/schemas/SomeSchema
pathPieces[3] = getKey(pathPieces[3], "schemas").snakeCase;
}
return;
} else if (pathPieces[2].equals("requestBodies")) {
pathPieces[2] = requestBodiesIdentifier;
} else if (pathPieces[2].equals("securitySchemes")) {
pathPieces[2] = securitySchemesIdentifier;
switch (pathPieces[2]) {
case "schemas":
// modelPackage replaces pathPieces[1] + pathPieces[2]
pathPieces[1] = modelPackagePathFragment();
pathPieces[2] = null;
if (pathPieces.length == 4) {
// #/components/schemas/SomeSchema
pathPieces[3] = getKey(pathPieces[3], "schemas").snakeCase;
}
return;
case "requestBodies":
pathPieces[2] = requestBodiesIdentifier;
break;
case "securitySchemes":
pathPieces[2] = securitySchemesIdentifier;
break;
}
if (pathPieces.length < 4) {
return;
Expand Down Expand Up @@ -3946,13 +3962,14 @@ public String sanitizeTag(String tag) {
return tag;
}

protected LinkedHashMapWithContext<EnumValue, String> getEnumValueToName(Schema schema, String currentJsonPath, String sourceJsonPath) {
protected EnumInfo getEnumInfo(Schema schema, String currentJsonPath, String sourceJsonPath, LinkedHashSet<String> types) {
if (schema.getEnum() == null) {
return null;
}

ArrayList<Object> values = new ArrayList<>(((Schema<?>) schema).getEnum());
LinkedHashMapWithContext<EnumValue, String> enumValueToName = new LinkedHashMapWithContext<>();
HashMap<String, List<EnumValue>> typeToValues = new LinkedHashMap<>();
LinkedHashMap<String, EnumValue> enumNameToValue = new LinkedHashMap<>();
int truncateIdx = 0;

Expand Down Expand Up @@ -4014,7 +4031,22 @@ protected LinkedHashMapWithContext<EnumValue, String> getEnumValueToName(Schema

String usedName = toEnumVarName(enumName, schema);
EnumValue enumValue = getEnumValue(value, description);
boolean typeIsInteger = enumValue.type.equals("integer");
boolean intIsNumberUseCase = (typeIsInteger && types!=null && types.contains("number"));
if (types!=null && !types.contains(enumValue.type) && !intIsNumberUseCase) {
throw new RuntimeException("Enum value's type is not allowed by schema types for value="+enumValue.value+" types="+types + " jsonPath="+currentJsonPath);
}
enumValueToName.put(enumValue, usedName);
if (!typeToValues.containsKey(enumValue.type)) {
typeToValues.put(enumValue.type, new ArrayList<>());
}
if (typeIsInteger && !typeToValues.containsKey("number")) {
typeToValues.put("number", new ArrayList<>());
}
typeToValues.get(enumValue.type).add(enumValue);
if (typeIsInteger) {
typeToValues.get("number").add(enumValue);
}

if (!enumNameToValue.containsKey(usedName)) {
enumNameToValue.put(usedName, enumValue);
Expand All @@ -4033,7 +4065,7 @@ protected LinkedHashMapWithContext<EnumValue, String> getEnumValueToName(Schema
enumValueToName.setJsonPathPiece(key);
}

return enumValueToName;
return new EnumInfo(enumValueToName, typeToValues);
}

/**
Expand Down Expand Up @@ -4367,8 +4399,7 @@ private String getRefModuleLocation(String ref) {
String prefix = outputFolder + File.separatorChar + "src" + File.separatorChar;
int endIndex = filePath.lastIndexOf(File.separatorChar);
String localFilepath = filePath.substring(prefix.length(), endIndex);
String refModuleLocation = localFilepath.replaceAll(String.valueOf(File.separatorChar), ".");
return refModuleLocation;
return localFilepath.replaceAll(String.valueOf(File.separatorChar), ".");
}

private String getRefModuleAlias(String refModuleLocation, String refModule) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -988,7 +988,7 @@ public void postProcessModelProperty(CodegenSchema model, CodegenSchema property
}
}

if (model.enumValueToName == null) {
if (model.enumInfo == null) {
// needed by all pojos, but not enums
model.imports.add("ApiModelProperty");
model.imports.add("ApiModel");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ public TreeMap<String, CodegenSchema> postProcessModels(TreeMap<String, CodegenS
}

for (CodegenSchema var : cm.properties.values()) {
if (var.enumValueToName != null || isSerializableModel()) {
if (var.enumInfo != null || isSerializableModel()) {
cm.vendorExtensions.put("x-has-data-class-body", true);
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -722,7 +722,7 @@ private static boolean isMultipartType(List<Map<String, String>> consumes) {
@Override
public void postProcessModelProperty(CodegenSchema model, CodegenSchema property) {
super.postProcessModelProperty(model, property);
if (model.enumValueToName == null) {
if (model.enumInfo == null) {
//final String lib = getLibrary();
//Needed imports for Jackson based libraries
if (additionalProperties.containsKey(SERIALIZATION_LIBRARY_JACKSON)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public void postProcessModelProperty(CodegenSchema model, CodegenSchema property
}

//Add imports for Jackson
if (model.enumValueToName == null) {
if (model.enumInfo == null) {
model.imports.add("JsonProperty");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class CodegenSchema {
public Integer maxProperties;
public Integer minProperties;
public LinkedHashMapWithContext<CodegenKey, CodegenSchema> requiredProperties; // used to store required info
public LinkedHashMapWithContext<EnumValue, String> enumValueToName; // enum info
public EnumInfo enumInfo;
public String type;
public ArrayListWithContext<CodegenSchema> allOf = null;
public ArrayListWithContext<CodegenSchema> anyOf = null;
Expand Down Expand Up @@ -248,13 +248,13 @@ private void getAllSchemas(ArrayList<CodegenSchema> schemasBeforeImports, ArrayL
schemasAfterImports.add(extraSchema);
}
}
if (enumValueToName != null) {
if (enumInfo != null) {
// write the class as a separate entity so enum values do not collide with
// json schema keywords
CodegenSchema extraSchema = new CodegenSchema();
extraSchema.jsonPathPiece = jsonPathPiece;
extraSchema.instanceType = "enumClass";
extraSchema.enumValueToName = enumValueToName;
extraSchema.enumInfo = enumInfo;
schemasBeforeImports.add(extraSchema);
}
boolean schemaAllAreInline = true;
Expand Down Expand Up @@ -480,7 +480,7 @@ protected void addInstanceInfo(StringBuilder sb) {
sb.append(", readOnly=").append(readOnly);
sb.append(", writeOnly=").append(writeOnly);
sb.append(", nullable=").append(nullable);
sb.append(", allowableValues=").append(enumValueToName);
sb.append(", allowableValues=").append(enumInfo);
sb.append(", items=").append(items);
sb.append(", additionalProperties=").append(additionalProperties);
sb.append(", vendorExtensions=").append(vendorExtensions);
Expand Down Expand Up @@ -566,7 +566,7 @@ public boolean equals(Object o) {
Objects.equals(example, that.example) &&
Objects.equals(minimum, that.minimum) &&
Objects.equals(maximum, that.maximum) &&
Objects.equals(enumValueToName, that.enumValueToName) &&
Objects.equals(enumInfo, that.enumInfo) &&
Objects.equals(items, that.items) &&
Objects.equals(additionalProperties, that.additionalProperties) &&
Objects.equals(vendorExtensions, that.vendorExtensions) &&
Expand All @@ -583,7 +583,7 @@ public int hashCode() {
maxLength, minLength, patternInfo, example, minimum, maximum,
exclusiveMinimum, exclusiveMaximum, deprecated, types,
readOnly, writeOnly, nullable,
enumValueToName, items, additionalProperties,
enumInfo, items, additionalProperties,
vendorExtensions, maxItems, minItems, xml,
schemaIsFromAdditionalProperties, isBooleanSchemaTrue, isBooleanSchemaFalse,
format, dependentRequired, contains, allOf, anyOf, oneOf, not,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.openapijsonschematools.codegen.model;

import java.util.HashMap;
import java.util.List;
import java.util.Objects;

public class EnumInfo {
public LinkedHashMapWithContext<EnumValue, String> valueToName; // enum info
public HashMap<String, List<EnumValue>> typeToValues;

public EnumInfo(LinkedHashMapWithContext<EnumValue, String> valueToName, HashMap<String, List<EnumValue>> typeToValues) {
this.valueToName = valueToName;
this.typeToValues = typeToValues;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
EnumInfo that = (EnumInfo) o;
return Objects.equals(valueToName, that.valueToName) &&
Objects.equals(typeToValues, that.typeToValues);
}

@Override
public int hashCode() {
return Objects.hash(valueToName, typeToValues);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{{#if enumValueToName}}
{{#if enumInfo}}


class {{enumValueToName.jsonPathPiece.camelCase}}:
{{#each enumValueToName}}
class {{enumInfo.valueToName.jsonPathPiece.camelCase}}:
{{#each enumInfo.valueToName}}

@schemas.classproperty
{{#eq @key.type "string"}}
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{{#unless refInfo.refClass}}{{#if enumValueToName}} must be one of [{{#each enumValueToName}}{{#unless @first}}, {{/unless}}{{#eq @key.type "null"}}None{{/eq}}{{#eq @key.type "boolean"}}{{#if @key.value}}True{{else}}False{{/if}}{{/eq}}{{#eq @key.type "string"}}"{{{@key.value}}}"{{/eq}}{{#eq @key.type "number"}}{{{@key.value}}}{{/eq}}{{#eq @key.type "integer"}}{{{@key.value}}}{{/eq}}{{/each}}]{{/if}}{{#if defaultValue}}{{#unless requiredProperties}} if omitted the {{defaultUser}} will use the default value of {{{defaultValue.value}}}{{/unless}}{{/if}}{{#eq format "uuid"}} value must be a uuid{{/eq}}{{#eq format "date"}} value must conform to RFC-3339 full-date YYYY-MM-DD{{/eq}}{{#eq format "date-time"}} value must conform to RFC-3339 date-time{{/eq}}{{#eq format "number"}} value must be int or float numeric{{/eq}}{{#eq format "int32"}} value must be a 32 bit integer{{/eq}}{{#eq format "int64"}} value must be a 64 bit integer{{/eq}}{{#eq format "double"}} value must be a 64 bit float{{/eq}}{{#eq format "float"}} value must be a 32 bit float{{/eq}}{{/unless}}
{{#unless refInfo.refClass}}{{#if enumInfo}} must be one of [{{#each enumInfo.valueToName}}{{#unless @first}}, {{/unless}}{{#eq @key.type "null"}}None{{/eq}}{{#eq @key.type "boolean"}}{{#if @key.value}}True{{else}}False{{/if}}{{/eq}}{{#eq @key.type "string"}}"{{{@key.value}}}"{{/eq}}{{#eq @key.type "number"}}{{{@key.value}}}{{/eq}}{{#eq @key.type "integer"}}{{{@key.value}}}{{/eq}}{{/each}}]{{/if}}{{#if defaultValue}}{{#unless requiredProperties}} if omitted the {{defaultUser}} will use the default value of {{{defaultValue.value}}}{{/unless}}{{/if}}{{#eq format "uuid"}} value must be a uuid{{/eq}}{{#eq format "date"}} value must conform to RFC-3339 full-date YYYY-MM-DD{{/eq}}{{#eq format "date-time"}} value must conform to RFC-3339 date-time{{/eq}}{{#eq format "number"}} value must be int or float numeric{{/eq}}{{#eq format "int32"}} value must be a 32 bit integer{{/eq}}{{#eq format "int64"}} value must be a 64 bit integer{{/eq}}{{#eq format "double"}} value must be a 64 bit float{{/eq}}{{#eq format "float"}} value must be a 32 bit float{{/eq}}{{/unless}}
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ class {{jsonPathPiece.camelCase}}(
{{#if format}}
format: str = '{{format}}'
{{/if}}
{{#if enumValueToName}}
{{#if enumInfo}}
{{> components/schemas/_helper_schema_enum }}
enums = {{enumValueToName.jsonPathPiece.camelCase}}
enums = {{enumInfo.valueToName.jsonPathPiece.camelCase}}
{{/if}}
{{#if items}}
{{> components/schemas/_helper_list_partial }}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
enum_value_to_name: typing.Mapping[typing.Union[int, float, str, bool, schemas.none_type_], str] = dataclasses.field(
enum_value_to_name: typing.Mapping[typing.Union[int, float, str, schemas.Bool, None], str] = dataclasses.field(
default_factory=lambda: {
{{#each enumValueToName}}
{{#each enumInfo.valueToName}}
{{#eq @key.type "string"}}
"{{{@key.value}}}": "{{this}}",
{{/eq}}
Expand Down
Loading