Skip to content

Commit 9e3ecb4

Browse files
committed
Android: Fix discount relationship
1 parent ce67c72 commit 9e3ecb4

File tree

3 files changed

+99
-21
lines changed

3 files changed

+99
-21
lines changed

Sources/SwagGenKit/KotlinFormatter.swift

Lines changed: 93 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,28 @@ public class KotlinFormatter: CodeFormatter {
5858
}
5959

6060
for index in filteredSchemas.indices {
61+
let schemaContext = filteredSchemas[index]
62+
var resourceType = getResourceType(context: schemaContext)
63+
64+
if resourceType == nil {
65+
let type = (schemaContext["properties"] as? [Context])?.first?["type"] as? String
66+
let schema = spec.components.schemas.first(where: {$0.name == type})
67+
if let schema = schema {
68+
let context = getSchemaContent(schema)
69+
resourceType = getResourceType(context: context)
70+
} else {
71+
let allProperties = schemaContext["allProperties"] as? [Context]
72+
let type = allProperties?.first(where: {$0["name"] as? String == "type"})?["type"] as? String
73+
let referencedSchema = spec.components.schemas.first(where: {$0.name == type})
74+
if let referencedSchema = referencedSchema {
75+
let referencedContext = getSchemaContent(referencedSchema)
76+
resourceType = getResourceType(context: referencedContext)
77+
}
78+
}
79+
}
80+
81+
filteredSchemas[index]["resourceType"] = resourceType
82+
6183
var relationships = filteredSchemas[index]["relationships"] as? [Context] ?? []
6284
for index in relationships.indices {
6385
var newProperties: [Context] = []
@@ -90,24 +112,43 @@ public class KotlinFormatter: CodeFormatter {
90112
}
91113
} else {
92114
let dataProperties = component.value.properties.first(where: {$0.name == "data"})?.schema.properties
93-
let type = dataProperties?.first(where: {$0.name == "type"})
94-
let enumValue = type?.enumValue?.cases.first as? String
95-
if let enumValue = enumValue {
96-
// Is relationship reference class e.g. PaymentMethodVendorRelationship
97-
// Find correct schema e.g. PaymentMethodVendor
98-
let schema = spec.components.schemas.first(where: {$0.name.lowercased() == enumValue.lowercased()})
115+
let raw = property["raw"] as? Context
116+
let reference = raw?["$ref"] as? String
117+
let last = reference?.split(separator: "/").last
118+
119+
if dataProperties == nil && last != nil {
120+
// Discount relationship
121+
let referenceType = String(last!)
122+
let referenceComponent = schemas.first(where: {$0["type"] as? String == referenceType})
123+
let referenceProperties = referenceComponent?["properties"] as? [Context]
124+
let hasMany = referenceProperties?.first(where: {$0["name"] as? String == "data"})?["isArray"]
125+
let schema = spec.components.schemas.first(where: {$0.name == type})
99126
if let schema = schema {
100127
var context = getSchemaContent(schema)
101128
context["name"] = name
102129
context["hasMany"] = hasMany
103130
newProperties.append(context)
104131
}
105132
} else {
106-
// Is already the correct schema e.g. GasStation
107-
var context = getSchemaContent(component)
108-
context["name"] = name
109-
context["hasMany"] = hasMany
110-
newProperties.append(context)
133+
let type = dataProperties?.first(where: {$0.name == "type"})
134+
let enumValue = type?.enumValue?.cases.first as? String
135+
if let enumValue = enumValue {
136+
// Is relationship reference class e.g. PaymentMethodVendorRelationship
137+
// Find correct schema e.g. PaymentMethodVendor
138+
let schema = spec.components.schemas.first(where: {$0.name.lowercased() == enumValue.lowercased()})
139+
if let schema = schema {
140+
var context = getSchemaContent(schema)
141+
context["name"] = name
142+
context["hasMany"] = hasMany
143+
newProperties.append(context)
144+
}
145+
} else {
146+
// Is already the correct schema e.g. GasStation
147+
var context = getSchemaContent(component)
148+
context["name"] = name
149+
context["hasMany"] = hasMany
150+
newProperties.append(context)
151+
}
111152
}
112153
}
113154
}
@@ -131,22 +172,52 @@ public class KotlinFormatter: CodeFormatter {
131172
var operations = context["operations"] as? [Context] ?? []
132173
for index in operations.indices {
133174
let successResponse = operations[index]["successResponse"] as? Context
134-
if var successResponse = successResponse {
175+
var successResponseType: String? = nil
176+
177+
if let successResponse = successResponse {
135178
let successResponseSchema = successResponse["schema"] as? Context
136179
let schema = (successResponseSchema?["properties"] as? [Context])?.first
180+
181+
successResponseType = schema?["type"] as? String
182+
if successResponseType == nil {
183+
successResponseType = (successResponseSchema)?["type"] as? String
184+
}
185+
137186
if let schema = schema {
138187
let resources = getResources(schemaContext: schema, allSchemas: filteredSchemas)
139-
successResponse["resources"] = Array(Set(resources))
140-
operations[index]["successResponse"] = successResponse
188+
operations[index]["resources"] = Array(Set(resources)).sorted()
189+
}
190+
}
191+
192+
if successResponseType == "File" {
193+
successResponseType = "ResponseBody"
194+
}
195+
196+
if let responseType = successResponseType {
197+
let schema = spec.components.schemas.first(where: {$0.name.lowercased() == responseType.lowercased()})
198+
let type = schema?.value.properties.first(where: {$0.name == "data"})?.schema.type
199+
if case .array = type {
200+
// Add List to response type if data is an array e.g. RegionalPrices should be List<RegionalPrices>
201+
successResponseType = "List<\(responseType)>"
141202
}
142203
}
204+
205+
operations[index]["successResponseType"] = successResponseType ?? "ResponseBody"
143206
}
144207

145208
context["operations"] = operations
146209

147210
return context
148211
}
149212

213+
private func getResourceType(context: Context) -> String? {
214+
let firstSchema = (context["schemas"] as? [Context])?.first
215+
let firstEnum = (context["enums"] as? [Context])?.first ?? (firstSchema?["enums"] as? [Context])?.first ?? (context["enum"] as? Context)
216+
let enumValue = (firstEnum?["enums"] as? [Context])?.first
217+
218+
return enumValue?["value"] as? String
219+
}
220+
150221
private func getResources(schemaContext: Context, allSchemas: [Context], allResources: [String] = []) -> [String] {
151222
var newAllResources = allResources
152223
let schemaType = schemaContext["type"] as? String
@@ -252,7 +323,14 @@ public class KotlinFormatter: CodeFormatter {
252323
if (firstPropertyName == "data") {
253324
let type = firstProperty?.schema.metadata.type
254325
if case .array = type {
255-
return "List<\(reference.name)>"
326+
let schemaType = reference.component.value.type.object?.properties.first?.schema.type
327+
if case .array(let arraySchema) = schemaType, case .single(let singleItem) = arraySchema.items {
328+
let enumValue = singleItem.type.object?.properties.first(where: {$0.name == "type"})?.schema.metadata.enumValues?.first as? String
329+
let referencesSchemaName = spec.components.schemas.first(where: {$0.name.lowercased() == enumValue?.lowercased()})?.name as? String
330+
if let referencesSchemaName {
331+
return referencesSchemaName
332+
}
333+
}
256334
}
257335
}
258336
return getSchemaTypeName(reference.component)

Templates/Kotlin/Common/Includes/Model.stencil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ typealias {{ type }} = {{ aliasType }}
1111
{% endif %}
1212
{% if type != "Data" %}
1313
{% if isResource %}
14-
@JsonApi(type = "{{ type|lowerCamelCase }}")
14+
@JsonApi(type = "{{ resourceType }}")
1515
class {{ type }} : Resource() {
1616
{% else %}
1717
class {{ type }} {

Templates/Kotlin/Common/Includes/ModelAPI.stencil

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ object {{ type }}API {
2222
{% endif %}
2323
@retrofit2.http.Body {{ body.name }}: {{ body.optionalType }}
2424
{% endif %}
25-
): Call<{% if successResponse.schema.properties.first.type %}{{ successResponse.schema.properties.first.type }}{% elif successResponse.schema.type and successResponse.schema.type != "File" %}{{ successResponse.schema.type }}{% else %}ResponseBody{% endif %}>
25+
): Call<{{ successResponseType }}>
2626
}
2727
{% for enum in requestEnums where not enum.isGlobal %}
2828

@@ -52,11 +52,11 @@ object {{ type }}API {
5252
{% if successResponse.schema.raw.type == "object" and successResponse.acceptHeaderEnums.count > 1 %}accept: {{type}}AcceptHeader? = null,{% endif %}
5353
additionalHeaders: Map<String, String>? = null,
5454
additionalParameters: Map<String, String>? = null
55-
): Call<{% if successResponse.schema.properties.first.type %}{{ successResponse.schema.properties.first.type }}{% elif successResponse.schema.type and successResponse.schema.type != "File" %}{{ successResponse.schema.type }}{% else %}ResponseBody{% endif %}> {
56-
{% if successResponse.resources.count > 0 %}val resources = listOf({% for resource in successResponse.resources %}{{ resource }}::class.java{% ifnot forloop.last %},{% endif %}{% endfor %}){% endif %}
55+
): Call<{{ successResponseType }}> {
56+
{% if resources.count > 0 %}val resources = listOf({% for resource in resources %}{{ resource }}::class.java{% ifnot forloop.last %},{% endif %}{% endfor %}){% endif %}
5757
val headers = headers({% if authorizationRequired == true %}true{% else %}false{% endif %}, {% if successResponse.schema.raw.type == "object" %}"application/vnd.api+json"{% elif contentType %}"{{contentType}}"{% else %}"application/json"{% endif %}, {% if successResponse.schema.raw.type == "object" and successResponse.acceptHeaderEnums.count > 1 %}null{% elif successResponse.schema.raw.type == "object" %}"application/vnd.api+json"{% elif contentType %}"{{contentType}}"{% else %}"application/json"{% endif %}, additionalHeaders)
5858

59-
return retrofit({{ options.modelProtocol }}.baseUrl, additionalParameters, readTimeout, {% if successResponse.resources.count > 0 %}resources{% endif %})
59+
return retrofit({{ options.modelProtocol }}.baseUrl, additionalParameters, readTimeout, {% if resources.count > 0 %}resources{% endif %})
6060
.create({{ type|upperCamelCase }}Service::class.java)
6161
.{{ type|lowerCamelCase }}(
6262
headers{% for param in nonBodyParams %},
@@ -82,7 +82,7 @@ object {{ type }}API {
8282
{% endfor %}
8383
{% if body %}{{ body.name }},{% endif %}
8484
readTimeout,
85-
{% if successResponse.schema.raw.type == "object" and successResponse.acceptHeaderEnums.count > 1 %}accept,{% endif %}
85+
{% if successResponse.schema.raw.type == "object" and successResponse.acceptHeaderEnums.count > 1 %}accept,{% endif %}
8686
additionalHeaders,
8787
additionalParameters
8888
)

0 commit comments

Comments
 (0)