Skip to content

Commit ca6447e

Browse files
committed
feat: support nested ecto arrays
1 parent 82cc2e5 commit ca6447e

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
@@ -302,12 +302,6 @@ public void execute(Template.Fragment fragment, Writer writer) throws IOExceptio
302302
writer.write(text.toUpperCase(Locale.ROOT));
303303
}
304304
});
305-
additionalProperties.put("toEctoType", new Mustache.Lambda() {
306-
@Override
307-
public void execute(Template.Fragment fragment, Writer writer) throws IOException {
308-
writer.write(toEctoType(fragment.execute()));
309-
}
310-
});
311305

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

392413
@Override
@@ -441,35 +462,6 @@ private String atomized(String text) {
441462
return atom.toString();
442463
}
443464

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

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