Skip to content

Commit 07b3af5

Browse files
committed
feat: support nested ecto arrays
1 parent faaa55f commit 07b3af5

8 files changed

Lines changed: 150 additions & 47 deletions

File tree

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

Lines changed: 139 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -303,12 +303,6 @@ public void execute(Template.Fragment fragment, Writer writer) throws IOExceptio
303303
writer.write(text.toUpperCase(Locale.ROOT));
304304
}
305305
});
306-
additionalProperties.put("toEctoType", new Mustache.Lambda() {
307-
@Override
308-
public void execute(Template.Fragment fragment, Writer writer) throws IOException {
309-
writer.write(toEctoType(fragment.execute()));
310-
}
311-
});
312306

313307
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
314308
setModuleName((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE));
@@ -387,7 +381,34 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
387381
@Override
388382
public CodegenModel fromModel(String name, Schema model) {
389383
CodegenModel cm = super.fromModel(name, model);
390-
return new ExtendedCodegenModel(cm);
384+
ExtendedCodegenModel ecm = new ExtendedCodegenModel(cm);
385+
386+
// Convert all CodegenProperty objects to ExtendedCodegenProperty
387+
List<CodegenProperty> vars = new ArrayList<>(ecm.vars);
388+
ecm.vars.clear();
389+
for (CodegenProperty var : vars) {
390+
ecm.vars.add(new ExtendedCodegenProperty(var));
391+
}
392+
393+
List<CodegenProperty> allVars = new ArrayList<>(ecm.allVars);
394+
ecm.allVars.clear();
395+
for (CodegenProperty var : allVars) {
396+
ecm.allVars.add(new ExtendedCodegenProperty(var));
397+
}
398+
399+
List<CodegenProperty> requiredVars = new ArrayList<>(ecm.requiredVars);
400+
ecm.requiredVars.clear();
401+
for (CodegenProperty var : requiredVars) {
402+
ecm.requiredVars.add(new ExtendedCodegenProperty(var));
403+
}
404+
405+
List<CodegenProperty> optionalVars = new ArrayList<>(ecm.optionalVars);
406+
ecm.optionalVars.clear();
407+
for (CodegenProperty var : optionalVars) {
408+
ecm.optionalVars.add(new ExtendedCodegenProperty(var));
409+
}
410+
411+
return ecm;
391412
}
392413

393414
@Override
@@ -442,35 +463,6 @@ private String atomized(String text) {
442463
return atom.toString();
443464
}
444465

445-
private String toEctoType(String baseType) {
446-
switch (baseType) {
447-
case "integer()":
448-
return ":integer";
449-
case "float()":
450-
return ":float";
451-
case "number()":
452-
return ":float";
453-
case "boolean()":
454-
return ":boolean";
455-
case "String.t":
456-
return ":string";
457-
case "Date.t":
458-
return ":date";
459-
case "DateTime.t":
460-
return ":utc_datetime";
461-
case "binary()":
462-
return ":binary";
463-
case "list()":
464-
return "{:array, :any}";
465-
case "map()":
466-
return ":map";
467-
case "nil":
468-
return ":any, virtual: true";
469-
default:
470-
return ":any, virtual: true";
471-
}
472-
}
473-
474466
/**
475467
* Escapes a reserved word as defined in the `reservedWords` array. Handle
476468
* escaping
@@ -969,6 +961,117 @@ public boolean hasComplexVars() {
969961
}
970962
}
971963

964+
class ExtendedCodegenProperty extends CodegenProperty {
965+
public ExtendedCodegenProperty(CodegenProperty cp) {
966+
super();
967+
968+
// Copy all fields of CodegenProperty
969+
this.openApiType = cp.openApiType;
970+
this.baseName = cp.baseName;
971+
this.complexType = cp.complexType;
972+
this.getter = cp.getter;
973+
this.setter = cp.setter;
974+
this.description = cp.description;
975+
this.dataType = cp.dataType;
976+
this.datatypeWithEnum = cp.datatypeWithEnum;
977+
this.dataFormat = cp.dataFormat;
978+
this.name = cp.name;
979+
this.min = cp.min;
980+
this.max = cp.max;
981+
this.defaultValue = cp.defaultValue;
982+
this.defaultValueWithParam = cp.defaultValueWithParam;
983+
this.baseType = cp.baseType;
984+
this.containerType = cp.containerType;
985+
this.title = cp.title;
986+
this.unescapedDescription = cp.unescapedDescription;
987+
this.maxLength = cp.maxLength;
988+
this.minLength = cp.minLength;
989+
this.pattern = cp.pattern;
990+
this.example = cp.example;
991+
this.jsonSchema = cp.jsonSchema;
992+
this.minimum = cp.minimum;
993+
this.maximum = cp.maximum;
994+
this.exclusiveMinimum = cp.exclusiveMinimum;
995+
this.exclusiveMaximum = cp.exclusiveMaximum;
996+
this.required = cp.required;
997+
this.deprecated = cp.deprecated;
998+
this.hasMoreNonReadOnly = cp.hasMoreNonReadOnly;
999+
this.isPrimitiveType = cp.isPrimitiveType;
1000+
this.isModel = cp.isModel;
1001+
this.isContainer = cp.isContainer;
1002+
this.isString = cp.isString;
1003+
this.isNumeric = cp.isNumeric;
1004+
this.isInteger = cp.isInteger;
1005+
this.isLong = cp.isLong;
1006+
this.isNumber = cp.isNumber;
1007+
this.isFloat = cp.isFloat;
1008+
this.isDouble = cp.isDouble;
1009+
this.isByteArray = cp.isByteArray;
1010+
this.isBinary = cp.isBinary;
1011+
this.isFile = cp.isFile;
1012+
this.isBoolean = cp.isBoolean;
1013+
this.isDate = cp.isDate;
1014+
this.isDateTime = cp.isDateTime;
1015+
this.isUuid = cp.isUuid;
1016+
this.isEmail = cp.isEmail;
1017+
this.isModel = cp.isModel;
1018+
this.isNull = cp.isNull;
1019+
this.isArray = cp.isArray;
1020+
this.isMap = cp.isMap;
1021+
this.isEnum = cp.isEnum;
1022+
this.isReadOnly = cp.isReadOnly;
1023+
this.isWriteOnly = cp.isWriteOnly;
1024+
this.isNullable = cp.isNullable;
1025+
this._enum = cp._enum;
1026+
this.allowableValues = cp.allowableValues;
1027+
this.items = cp.items;
1028+
this.additionalProperties = cp.additionalProperties;
1029+
this.vars = cp.vars;
1030+
this.requiredVars = cp.requiredVars;
1031+
this.vendorExtensions = cp.vendorExtensions;
1032+
}
1033+
1034+
public String ectoType() {
1035+
String ectoType = ectoType(this);
1036+
1037+
if (":any".equals(ectoType)) {
1038+
return ectoType + ", virtual: true";
1039+
}
1040+
1041+
return ectoType;
1042+
}
1043+
1044+
private String ectoType(CodegenProperty property) {
1045+
String baseType = property.baseType;
1046+
switch (baseType) {
1047+
case "integer()":
1048+
return ":integer";
1049+
case "float()":
1050+
return ":float";
1051+
case "number()":
1052+
return ":float";
1053+
case "boolean()":
1054+
return ":boolean";
1055+
case "String.t":
1056+
return ":string";
1057+
case "Date.t":
1058+
return ":date";
1059+
case "DateTime.t":
1060+
return ":utc_datetime";
1061+
case "binary()":
1062+
return ":binary";
1063+
case "list()":
1064+
return "{:array, " + ectoType(property.items) + "}";
1065+
case "map()":
1066+
return ":map";
1067+
case "nil":
1068+
return ":any";
1069+
default:
1070+
return ":any";
1071+
}
1072+
}
1073+
}
1074+
9721075
@Override
9731076
public String escapeQuotationMark(String input) {
9741077
return input.replace("\"", "");

modules/openapi-generator/src/main/resources/elixir/model.mustache

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
typed_embedded_schema do
1111
{{#vars}}
1212
{{#isPrimitiveType}}
13-
field {{#atom}}{{&baseName}}{{/atom}}, {{#toEctoType}}{{{baseType}}}{{/toEctoType}}{{#required}}, null: false{{/required}}
13+
field {{#atom}}{{&baseName}}{{/atom}}, {{{ectoType}}}{{#required}}, null: false{{/required}}
1414
{{/isPrimitiveType}}
1515
{{^isPrimitiveType}}
1616
{{^isArray}}embeds_one{{/isArray}}{{#isArray}}embeds_many{{/isArray}} {{#atom}}{{&baseName}}{{/atom}}, {{&moduleName}}.Model.{{^isArray}}{{{baseType}}}{{/isArray}}{{#isArray}}{{{items.baseType}}}{{/isArray}}{{#isNullable}}, null: true{{/isNullable}}

samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_array_of_number_only.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ defmodule OpenapiPetstore.Model.ArrayOfArrayOfNumberOnly do
1010
@derive {JSON.Encoder, only: [:ArrayArrayNumber]}
1111
@primary_key false
1212
typed_embedded_schema do
13-
field :ArrayArrayNumber, {:array, :any}
13+
field :ArrayArrayNumber, {:array, {:array, :float}}
1414
end
1515

1616
@spec new(map()) :: t()

samples/client/petstore/elixir/lib/openapi_petstore/model/array_of_number_only.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ defmodule OpenapiPetstore.Model.ArrayOfNumberOnly do
1010
@derive {JSON.Encoder, only: [:ArrayNumber]}
1111
@primary_key false
1212
typed_embedded_schema do
13-
field :ArrayNumber, {:array, :any}
13+
field :ArrayNumber, {:array, :float}
1414
end
1515

1616
@spec new(map()) :: t()

samples/client/petstore/elixir/lib/openapi_petstore/model/array_test.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ defmodule OpenapiPetstore.Model.ArrayTest do
1010
@derive {JSON.Encoder, only: [:array_of_string, :array_array_of_integer, :array_array_of_model]}
1111
@primary_key false
1212
typed_embedded_schema do
13-
field :array_of_string, {:array, :any}
14-
field :array_array_of_integer, {:array, :any}
15-
field :array_array_of_model, {:array, :any}
13+
field :array_of_string, {:array, :string}
14+
field :array_array_of_integer, {:array, {:array, :integer}}
15+
field :array_array_of_model, {:array, {:array, :any}}
1616
end
1717

1818
@spec new(map()) :: t()

samples/client/petstore/elixir/lib/openapi_petstore/model/enum_arrays.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ defmodule OpenapiPetstore.Model.EnumArrays do
1111
@primary_key false
1212
typed_embedded_schema do
1313
field :just_symbol, :string
14-
field :array_enum, {:array, :any}
14+
field :array_enum, {:array, :string}
1515
end
1616

1717
@spec new(map()) :: t()

samples/client/petstore/elixir/lib/openapi_petstore/model/nullable_class.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ defmodule OpenapiPetstore.Model.NullableClass do
1616
field :string_prop, :string
1717
field :date_prop, :date
1818
field :datetime_prop, :utc_datetime
19-
field :array_nullable_prop, {:array, :any}
20-
field :array_and_items_nullable_prop, {:array, :any}
21-
field :array_items_nullable, {:array, :any}
19+
field :array_nullable_prop, {:array, :map}
20+
field :array_and_items_nullable_prop, {:array, :map}
21+
field :array_items_nullable, {:array, :map}
2222
field :object_nullable_prop, :map
2323
field :object_and_items_nullable_prop, :map
2424
field :object_items_nullable, :map

samples/client/petstore/elixir/lib/openapi_petstore/model/object_with_deprecated_fields.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ defmodule OpenapiPetstore.Model.ObjectWithDeprecatedFields do
1313
field :uuid, :string
1414
field :id, :float
1515
embeds_one :deprecatedRef, OpenapiPetstore.Model.DeprecatedModel
16-
field :bars, {:array, :any}
16+
field :bars, {:array, :string}
1717
end
1818

1919
@spec new(map()) :: t()

0 commit comments

Comments
 (0)