Skip to content

Commit df4a7e7

Browse files
authored
Merge pull request #676 from Backbase/fix/free-form-object-issue
Fix/Free-Form Object issue with `boat-swift5` generator
2 parents 6b49778 + 71db033 commit df4a7e7

4 files changed

Lines changed: 262 additions & 79 deletions

File tree

boat-maven-plugin/src/main/java/com/backbase/oss/boat/GenerateMojo.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -771,30 +771,30 @@ public void execute() throws MojoExecutionException, MojoFailureException {
771771
GlobalSettings.setProperty(CodegenConstants.WITH_XML, withXml.toString());
772772

773773
if (configOptions != null) {
774-
// Retained for backwards-compataibility with configOptions -> instantiation-types
774+
// Retained for backwards-compatibility with configOptions -> instantiation-types
775775
if (instantiationTypes == null && configOptions.containsKey(INSTANTIATION_TYPES)) {
776776
applyInstantiationTypesKvp(configOptions.get(INSTANTIATION_TYPES).toString(),
777777
configurator);
778778
}
779779

780-
// Retained for backwards-compataibility with configOptions -> import-mappings
780+
// Retained for backwards-compatibility with configOptions -> import-mappings
781781
if (importMappings == null && configOptions.containsKey(IMPORT_MAPPINGS)) {
782782
applyImportMappingsKvp(configOptions.get(IMPORT_MAPPINGS).toString(),
783783
configurator);
784784
}
785785

786-
// Retained for backwards-compataibility with configOptions -> type-mappings
786+
// Retained for backwards-compatibility with configOptions -> type-mappings
787787
if (typeMappings == null && configOptions.containsKey(TYPE_MAPPINGS)) {
788788
applyTypeMappingsKvp(configOptions.get(TYPE_MAPPINGS).toString(), configurator);
789789
}
790790

791-
// Retained for backwards-compataibility with configOptions -> language-specific-primitives
791+
// Retained for backwards-compatibility with configOptions -> language-specific-primitives
792792
if (languageSpecificPrimitives == null && configOptions.containsKey(LANGUAGE_SPECIFIC_PRIMITIVES)) {
793793
applyLanguageSpecificPrimitivesCsv(configOptions
794794
.get(LANGUAGE_SPECIFIC_PRIMITIVES).toString(), configurator);
795795
}
796796

797-
// Retained for backwards-compataibility with configOptions -> additional-properties
797+
// Retained for backwards-compatibility with configOptions -> additional-properties
798798
if (additionalProperties == null && configOptions.containsKey(ADDITIONAL_PROPERTIES)) {
799799
applyAdditionalPropertiesKvp(configOptions.get(ADDITIONAL_PROPERTIES).toString(),
800800
configurator);
@@ -804,7 +804,7 @@ public void execute() throws MojoExecutionException, MojoFailureException {
804804
applyServerVariablesKvp(configOptions.get(SERVER_VARIABLES).toString(), configurator);
805805
}
806806

807-
// Retained for backwards-compataibility with configOptions -> reserved-words-mappings
807+
// Retained for backwards-compatibility with configOptions -> reserved-words-mappings
808808
if (reservedWordsMappings == null && configOptions.containsKey(RESERVED_WORDS_MAPPINGS)) {
809809
applyReservedWordsMappingsKvp(configOptions.get(RESERVED_WORDS_MAPPINGS)
810810
.toString(), configurator);
@@ -960,8 +960,8 @@ protected Collection<String> getGeneratorSpecificSupportingFiles() {
960960
/**
961961
* Calculate openapi specification file hash. If specification is hosted on remote resource it is downloaded first
962962
*
963-
* @param inputSpecFile - Openapi specification input file to calculate it's hash.
964-
* Does not taken into account if input spec is hosted on remote resource
963+
* @param inputSpecFile - Openapi specification input file to calculate its hash.
964+
* Does not take into account if input spec is hosted on remote resource
965965
* @return openapi specification file hash
966966
* @throws IOException When cannot read the file
967967
*/
@@ -1019,8 +1019,8 @@ private URL inputSpecRemoteUrl() {
10191019
/**
10201020
* Get specification hash file.
10211021
*
1022-
* @param inputSpecFile - Openapi specification input file to calculate it's hash.
1023-
* Does not taken into account if input spec is hosted on remote resource
1022+
* @param inputSpecFile - Openapi specification input file to calculate its hash.
1023+
* Does not take into account if input spec is hosted on remote resource
10241024
* @return a file with previously calculated hash
10251025
*/
10261026
private File getHashFile(File inputSpecFile) {
@@ -1073,7 +1073,7 @@ private void addCompileSourceRootIfConfigured() {
10731073
* config.additionalProperties (configuration/configOptions) to proper booleans.
10741074
* This enables mustache files to handle the properties better.
10751075
*
1076-
* @param config GodeGen config
1076+
* @param config CodeGen config
10771077
*/
10781078
private void adjustAdditionalProperties(final CodegenConfig config) {
10791079
Map<String, Object> configAdditionalProperties = config.additionalProperties();

boat-scaffold/src/main/java/org/openapitools/codegen/languages/BoatSwift5Codegen.java

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import io.swagger.v3.oas.models.media.Schema;
55
import org.openapitools.codegen.CodegenConfig;
66
import org.openapitools.codegen.CodegenModel;
7+
import org.openapitools.codegen.CodegenProperty;
78
import org.openapitools.codegen.SupportingFile;
89
import org.openapitools.codegen.meta.GeneratorMetadata;
910
import org.openapitools.codegen.meta.Stability;
@@ -31,6 +32,12 @@ public BoatSwift5Codegen() {
3132

3233
// Set the default template directory
3334
embeddedTemplateDir = templateDir = getName();
35+
36+
// Type mappings //
37+
this.typeMapping.remove("object");
38+
this.typeMapping.remove("AnyType");
39+
this.typeMapping.put("object", "Any");
40+
this.typeMapping.put("AnyType", "Any");
3441
}
3542

3643
@Override
@@ -62,6 +69,53 @@ public String getTypeDeclaration(Schema p) {
6269
return super.getTypeDeclaration(p);
6370
}
6471

72+
@Override
73+
public CodegenModel fromModel(String name, Schema model) {
74+
Map<String, Schema> allDefinitions = ModelUtils.getSchemas(this.openAPI);
75+
CodegenModel codegenModel = super.fromModel(name, model);
76+
if (codegenModel.description != null) {
77+
codegenModel.imports.add("ApiModel");
78+
}
79+
80+
fixAllFreeFormObject(codegenModel);
81+
82+
return codegenModel;
83+
}
84+
85+
/*
86+
This is added as a compatibility requirement for API specs containing free form objects
87+
missing `additionalProperties` property
88+
*/
89+
private void fixAllFreeFormObject(CodegenModel codegenModel) {
90+
this.fixFreeFormObject(codegenModel.vars);
91+
this.fixFreeFormObject(codegenModel.optionalVars);
92+
this.fixFreeFormObject(codegenModel.requiredVars);
93+
this.fixFreeFormObject(codegenModel.parentVars);
94+
this.fixFreeFormObject(codegenModel.allVars);
95+
this.fixFreeFormObject(codegenModel.readOnlyVars);
96+
this.fixFreeFormObject(codegenModel.readWriteVars);
97+
}
98+
99+
/*
100+
If a property has both isFreeFormObject and isMapContainer true make isFreeFormObject false
101+
This way when we have a free form object in the spec that has a typed value it will be
102+
treated as a Dictionary
103+
*/
104+
private void fixFreeFormObject(List<CodegenProperty> codegenProperties) {
105+
for (CodegenProperty codegenProperty : codegenProperties) {
106+
if (codegenProperty.isFreeFormObject && codegenProperty.isMap && !codegenProperty.items.isFreeFormObject) {
107+
codegenProperty.isFreeFormObject = false;
108+
}
109+
110+
if (codegenProperty.isArray && codegenProperty.items.isFreeFormObject) {
111+
codegenProperty.isFreeFormObject = true;
112+
if (codegenProperty.additionalProperties == null) {
113+
codegenProperty.isMap = false;
114+
}
115+
}
116+
}
117+
}
118+
65119
// Fix for inheritance bug
66120
@Override
67121
public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs) {
@@ -113,7 +167,7 @@ private void fixInheritance(CodegenModel codegenModel, CodegenModel parentModel)
113167
@Override
114168
public void postProcess() {
115169
System.out.println("################################################################################");
116-
System.out.println("# Thanks for using BOAT Swift OpenAPI Generator. #");
170+
System.out.println("# Thanks for using BOAT Swift 5 OpenAPI Generator. #");
117171
System.out.println("################################################################################");
118172
}
119173

Lines changed: 53 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,33 @@
11
{{#allParams}}
2-
{{#isEnum}}
3-
{{> modelInlineEnumDeclaration}}
4-
{{/isEnum}}
2+
{{#isEnum}}
3+
{{> modelInlineEnumDeclaration}}
4+
{{/isEnum}}
55
{{/allParams}}
66
{{#allParams}}
7-
{{#isEnum}}
8-
{{#description}}/** {{description}} */
9-
{{/description}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let {{paramName}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}
10-
{{/isEnum}}
11-
{{^isEnum}}
12-
{{#description}}/** {{description}} */
13-
{{/description}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let {{paramName}}: {{{dataType}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}
14-
{{#objcCompatible}}
15-
{{#vendorExtensions.x-swift-optional-scalar}}
16-
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var {{paramName}}Num: NSNumber? {
17-
get {
18-
return {{paramName}}.map({ return NSNumber(value: $0) })
19-
}
20-
}
21-
{{/vendorExtensions.x-swift-optional-scalar}}
22-
{{/objcCompatible}}
23-
{{/isEnum}}
7+
{{#isEnum}}
8+
{{#description}}/** {{description}} */
9+
{{/description}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let {{paramName}}: {{{datatypeWithEnum}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}
10+
{{/isEnum}}
11+
{{^isEnum}}
12+
{{#description}}/** {{description}} */
13+
{{/description}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} let {{paramName}}: {{{dataType}}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}
14+
{{#objcCompatible}}
15+
{{#vendorExtensions.x-swift-optional-scalar}}
16+
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var {{paramName}}Num: NSNumber? {
17+
get {
18+
return {{paramName}}.map({ return NSNumber(value: $0) })
19+
}
20+
}
21+
{{/vendorExtensions.x-swift-optional-scalar}}
22+
{{/objcCompatible}}
23+
{{/isEnum}}
2424
{{/allParams}}
2525

2626
{{#hasParams}}
2727
internal init({{#allParams}}{{paramName}}: {{#isEnum}}{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}{{^required}}?{{/required}}{{^-last}}, {{/-last}}{{/allParams}}) {
28-
{{#allParams}}
28+
{{#allParams}}
2929
self.{{paramName}} = {{paramName}}
30-
{{/allParams}}
30+
{{/allParams}}
3131
}
3232
{{/hasParams}}
3333
{{#hasParams}}
@@ -36,47 +36,47 @@
3636
{{#allParams}}
3737
{{#description}}/** {{description}} */
3838
{{/description}}{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} {{#required}}let{{/required}}{{^required}}private(set) var{{/required}} {{> api_param_builder}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/required}}
39-
{{^isEnum}}
40-
{{#objcCompatible}}
41-
{{#vendorExtensions.x-swift-optional-scalar}}
42-
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var {{paramName}}Num: NSNumber? {
43-
get {
44-
return {{paramName}}.map({ return NSNumber(value: $0) })
45-
}
46-
}
47-
{{/vendorExtensions.x-swift-optional-scalar}}
48-
{{/objcCompatible}}
49-
{{/isEnum}}
39+
{{^isEnum}}
40+
{{#objcCompatible}}
41+
{{#vendorExtensions.x-swift-optional-scalar}}
42+
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} var {{paramName}}Num: NSNumber? {
43+
get {
44+
return {{paramName}}.map({ return NSNumber(value: $0) })
45+
}
46+
}
47+
{{/vendorExtensions.x-swift-optional-scalar}}
48+
{{/objcCompatible}}
49+
{{/isEnum}}
5050
{{/allParams}}
5151

52-
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init({{#requiredParams}}{{^-first}}, {{/-first}}{{> api_param_builder}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/requiredParams}}) {
53-
{{#requiredParams}}
54-
self.{{paramName}} = {{paramName}}
55-
{{/requiredParams}}
56-
}
52+
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} init({{#requiredParams}}{{^-first}}, {{/-first}}{{> api_param_builder}}{{#defaultValue}} = {{{defaultValue}}}{{/defaultValue}}{{/requiredParams}}) {
53+
{{#requiredParams}}
54+
self.{{paramName}} = {{paramName}}
55+
{{/requiredParams}}
56+
}
5757

5858
{{#optionalParams}}
5959
/// Setter method for {{paramName}} property.
6060
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func set({{> api_param_builder}}?) -> Self {
61-
self.{{paramName}} = {{paramName}}
62-
return self
61+
self.{{paramName}} = {{paramName}}
62+
return self
6363
}
6464
{{/optionalParams}}
6565

66-
/// Builder initializer method for {{operationIdCamelCase}}RequestParams DTO.
67-
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func build() -> {{operationIdCamelCase}}RequestParams {
68-
return {{operationIdCamelCase}}RequestParams({{#allParams}}{{paramName}}: {{paramName}}{{^-last}},
69-
{{/-last}}{{/allParams}})
70-
}
66+
/// Builder initializer method for {{operationIdCamelCase}}RequestParams DTO.
67+
{{#nonPublicApi}}internal{{/nonPublicApi}}{{^nonPublicApi}}public{{/nonPublicApi}} func build() -> {{operationIdCamelCase}}RequestParams {
68+
return {{operationIdCamelCase}}RequestParams({{#allParams}}{{paramName}}: {{paramName}}{{^-last}},
69+
{{/-last}}{{/allParams}})
70+
}
7171

72-
public static func ==(lhs: Builder, rhs: Builder) -> Bool {
73-
return {{^hasParams}}true{{/hasParams}}{{#allParams}}{{#isFreeFormObject}}{{#isMap}}lhs.{{paramName}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}.mapValues { AnyCodable($0) } == rhs.{{paramName}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}.mapValues { AnyCodable($0) }{{/isMap}}{{^isMap}}AnyCodable(lhs.{{paramName}}) == AnyCodable(rhs.{{paramName}}){{/isMap}}{{/isFreeFormObject}}{{^isFreeFormObject}}lhs.{{paramName}}{{#isArray}}{{^required}}?{{/required}}.description{{/isArray}} == rhs.{{paramName}}{{#isArray}}{{^required}}?{{/required}}.description{{/isArray}}{{/isFreeFormObject}}{{^-last}} &&
74-
{{/-last}}{{/allParams}}
75-
}
72+
public static func ==(lhs: Builder, rhs: Builder) -> Bool {
73+
return {{^hasParams}}true{{/hasParams}}{{#allParams}}{{#isFreeFormObject}}AnyCodable(lhs.{{paramName}}) == AnyCodable(rhs.{{paramName}}){{/isFreeFormObject}}{{^isFreeFormObject}}lhs.{{paramName}}{{#isArray}}{{^required}}?{{/required}}.description{{/isArray}} == rhs.{{paramName}}{{#isArray}}{{^required}}?{{/required}}.description{{/isArray}}{{/isFreeFormObject}}{{^-last}} &&
74+
{{/-last}}{{/allParams}}
75+
}
7676
}
7777
{{/hasParams}}
7878

79-
public static func ==(lhs: Self, rhs: Self) -> Bool {
80-
return {{^hasParams}}true{{/hasParams}}{{#allParams}}{{#isFreeFormObject}}{{#isMap}}lhs.{{paramName}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}.mapValues { AnyCodable($0) } == rhs.{{paramName}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^required}}?{{/required}}.mapValues { AnyCodable($0) }{{/isMap}}{{^isMap}}AnyCodable(lhs.{{paramName}}) == AnyCodable(rhs.{{paramName}}){{/isMap}}{{/isFreeFormObject}}{{^isFreeFormObject}}lhs.{{paramName}}{{#isArray}}{{^required}}?{{/required}}.description{{/isArray}} == rhs.{{paramName}}{{#isArray}}{{^required}}?{{/required}}.description{{/isArray}}{{/isFreeFormObject}}{{^-last}} &&
81-
{{/-last}}{{/allParams}}
82-
}
79+
public static func ==(lhs: Self, rhs: Self) -> Bool {
80+
return {{^hasParams}}true{{/hasParams}}{{#allParams}}{{#isFreeFormObject}}AnyCodable(lhs.{{paramName}}) == AnyCodable(rhs.{{paramName}}){{/isFreeFormObject}}{{^isFreeFormObject}}lhs.{{paramName}}{{#isArray}}{{^required}}?{{/required}}.description{{/isArray}} == rhs.{{paramName}}{{#isArray}}{{^required}}?{{/required}}.description{{/isArray}}{{/isFreeFormObject}}{{^-last}} &&
81+
{{/-last}}{{/allParams}}
82+
}

0 commit comments

Comments
 (0)