Skip to content

Commit d9366ab

Browse files
authored
Support for dynamic initialization of nested classes (#461)
When classes are nested, child classes were not initialized. This caused the following problems - Need to write webhook parser by hand with detailed conditionals #404 - Responses could not be parsed correctly #440 This PR resolves those problems. This also adds support for `MembershipEvent`, which was not supported by the webhook parser. 61c4a5a
1 parent 9e34215 commit d9366ab

569 files changed

Lines changed: 5480 additions & 745 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

generator/src/main/java/line/bot/generator/LineBotSdkRubyGenerator.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import java.io.File;
44
import java.util.HashMap;
5+
import java.util.List;
56
import java.util.Map;
67
import java.util.Optional;
8+
import java.util.stream.Collectors;
79

810
import org.openapitools.codegen.CodegenDiscriminator;
911
import org.openapitools.codegen.CodegenModel;
@@ -79,19 +81,42 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
7981
for (ModelsMap entry : result.values()) {
8082
for (ModelMap mo : entry.getModels()) {
8183
CodegenModel cm = mo.getModel();
84+
final Map<String, Object> selector = new HashMap<>();
8285

8386
if (cm.getParentModel() != null) {
8487
final CodegenDiscriminator discriminator = cm.getParentModel().getDiscriminator();
8588
final Optional<String> mappingNameOptional = discriminator.getMappedModels().stream().filter(
8689
it -> it.getModelName().equals(cm.name)
8790
).map(CodegenDiscriminator.MappedModel::getMappingName).findFirst();
8891
mappingNameOptional.ifPresent(mappingName -> {
89-
final Map<String, Object> selector = new HashMap<>();
9092
selector.put("propertyName", discriminator.getPropertyName());
9193
selector.put("mappingName", mappingName);
9294
cm.getVendorExtensions().put("x-selector", selector);
9395
});
9496
}
97+
98+
if (cm.getChildren() != null && cm.getDiscriminator() != null) {
99+
final List<Map<String, String>> childMappings =
100+
cm.getChildren().stream()
101+
.map(child -> {
102+
Map<String, String> childInfo = new HashMap<>();
103+
childInfo.put("className", child.name);
104+
105+
final CodegenDiscriminator discriminator = cm.getDiscriminator();
106+
if (discriminator != null) {
107+
discriminator.getMappedModels().stream()
108+
.filter(mappedModel -> mappedModel.getModelName().equals(child.name))
109+
.findFirst()
110+
.ifPresent(mappedModel -> childInfo.put("typeName", mappedModel.getMappingName()));
111+
}
112+
113+
return childInfo;
114+
})
115+
.collect(Collectors.toList());
116+
117+
cm.getVendorExtensions().put("x-children", childMappings);
118+
cm.getVendorExtensions().put("x-discriminator-property", cm.getDiscriminator().getPropertyName());
119+
}
95120
}
96121
}
97122
return result;

generator/src/main/java/line/bot/generator/LineBotSdkRubyRbsGenerator.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
import java.io.File;
44
import java.util.HashMap;
5+
import java.util.List;
56
import java.util.Map;
67
import java.util.Optional;
8+
import java.util.stream.Collectors;
79

810
import org.openapitools.codegen.CodegenDiscriminator;
911
import org.openapitools.codegen.CodegenModel;
@@ -80,19 +82,42 @@ public Map<String, ModelsMap> postProcessAllModels(Map<String, ModelsMap> objs)
8082
for (ModelsMap entry : result.values()) {
8183
for (ModelMap mo : entry.getModels()) {
8284
CodegenModel cm = mo.getModel();
85+
final Map<String, Object> selector = new HashMap<>();
8386

8487
if (cm.getParentModel() != null) {
8588
final CodegenDiscriminator discriminator = cm.getParentModel().getDiscriminator();
8689
final Optional<String> mappingNameOptional = discriminator.getMappedModels().stream().filter(
8790
it -> it.getModelName().equals(cm.name)
8891
).map(CodegenDiscriminator.MappedModel::getMappingName).findFirst();
8992
mappingNameOptional.ifPresent(mappingName -> {
90-
final Map<String, Object> selector = new HashMap<>();
9193
selector.put("propertyName", discriminator.getPropertyName());
9294
selector.put("mappingName", mappingName);
9395
cm.getVendorExtensions().put("x-selector", selector);
9496
});
9597
}
98+
99+
if (cm.getChildren() != null && cm.getDiscriminator() != null) {
100+
final List<Map<String, String>> childMappings =
101+
cm.getChildren().stream()
102+
.map(child -> {
103+
Map<String, String> childInfo = new HashMap<>();
104+
childInfo.put("className", child.name);
105+
106+
final CodegenDiscriminator discriminator = cm.getDiscriminator();
107+
if (discriminator != null) {
108+
discriminator.getMappedModels().stream()
109+
.filter(mappedModel -> mappedModel.getModelName().equals(child.name))
110+
.findFirst()
111+
.ifPresent(mappedModel -> childInfo.put("typeName", mappedModel.getMappingName()));
112+
}
113+
114+
return childInfo;
115+
})
116+
.collect(Collectors.toList());
117+
118+
cm.getVendorExtensions().put("x-children", childMappings);
119+
cm.getVendorExtensions().put("x-discriminator-property", cm.getDiscriminator().getPropertyName());
120+
}
96121
}
97122
}
98123
return result;

generator/src/main/resources/line-bot-sdk-ruby-generator/model.pebble

Lines changed: 42 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,57 @@ module Line
2525
{% if model.model.vendorExtensions.get("x-selector").propertyName != property.name %}attr_accessor{% else %}attr_reader{% endif %} :{{ property.name }}{% if property.description != null %} # {{ property.description }}{% endif %}
2626
{%- endfor %}
2727

28-
def initialize({% for property in model.model.vars %}{% if model.model.vendorExtensions.get("x-selector").propertyName != property.name or packageName == 'webhook' %}
28+
def initialize({% for property in model.model.vars %}{% if model.model.vendorExtensions.get("x-selector").propertyName != property.name %}
2929
{{ property.name }}:{% if property.defaultValue == null %}{{ property.required ? '' : ' nil' }}{% else %}{{ ' ' + property.defaultValue }}{% endif %},{% endif %}{% endfor %}
3030
**dynamic_attributes
3131
)
32-
{% if model.model.vendorExtensions.get("x-selector") != null %}@{{model.model.vendorExtensions.get("x-selector").propertyName}} = "{{model.model.vendorExtensions.get("x-selector").mappingName}}"{% endif -%}
32+
{% if model.model.vendorExtensions.get("x-selector") != null %}@{{model.model.vendorExtensions.get("x-selector").propertyName}} = "{{model.model.vendorExtensions.get("x-selector").mappingName}}"{%- endif -%}
3333
{%- for property in model.model.vars %}
34-
{% if model.model.vendorExtensions.get("x-selector").propertyName != property.name %}@{{ property.name }} = {{ property.name }}{% endif -%}
35-
{% endfor %}
34+
{% if property.isArray -%}
35+
@{{ property.name }} = {{ property.name }}{{ property.required ? '' : '&' }}.map do |item|
36+
if item.is_a?(Hash)
37+
Line::Bot::V2::{{ packageName | camelize }}::{{ property.complexType }}.create(**item)
38+
else
39+
item
40+
end
41+
end
42+
{%- elseif property.isModel -%}
43+
@{{ property.name }} = {{ property.name }}.is_a?(Line::Bot::V2::{{ packageName | camelize }}::{{ property.baseType }}){% if not property.required %} || {{ property.name }}.nil?{% endif %} ? {{ property.name }} : Line::Bot::V2::{{ packageName | camelize }}::{{ property.baseType }}.create(**{{ property.name }})
44+
{%- elseif model.model.vendorExtensions.get("x-selector").propertyName != property.name -%}
45+
@{{ property.name }} = {{ property.name }}
46+
{%- endif -%}
47+
{%- endfor %}
3648

3749
dynamic_attributes.each do |key, value|
3850
self.class.attr_accessor key
39-
instance_variable_set("@#{key}", value)
51+
52+
if value.is_a?(Hash)
53+
struct_klass = Struct.new(*value.keys.map(&:to_sym))
54+
struct_values = value.map { |_k, v| v.is_a?(Hash) ? Line::Bot::V2::Utils.hash_to_struct(v) : v }
55+
instance_variable_set("@#{key}", struct_klass.new(*struct_values))
56+
else
57+
instance_variable_set("@#{key}", value)
58+
end
4059
end
4160
end
61+
62+
def self.create(args){% if model.model.vendorExtensions.get("x-children") != null and model.model.vendorExtensions.get("x-discriminator-property") != null %}
63+
klass = detect_class(args[:{{ model.model.vendorExtensions.get("x-discriminator-property") }}])
64+
return klass.new(**args) if klass
65+
{% endif %}
66+
return new(**args)
67+
end
68+
{%- if model.model.vendorExtensions.get("x-children") != null %}
69+
70+
private
71+
72+
def self.detect_class(type)
73+
{
74+
{%- for child in model.model.vendorExtensions.get("x-children") %}
75+
{{ child.typeName }}: Line::Bot::V2::{{ packageName | camelize }}::{{ child.className }},
76+
{%- endfor %}
77+
}[type.to_sym]
78+
end{% endif %}
4279
end
4380
end
4481
end

generator/src/main/resources/line-bot-sdk-ruby-rbs-generator/model.pebble

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,14 @@ module Line
5858
{% endif %}{{ loop.last ? '' : ",
5959
" }}{% endif %}{% endfor %}
6060
) -> void
61+
62+
def self.create: (args: Hash[Symbol, untyped]) -> {{ model.model.classname }}
63+
{%- if model.model.vendorExtensions.get("x-children") != null %}
64+
65+
private
66+
67+
def self.detect_class: (type: String) -> Class
68+
{%- endif %}
6169
{%- endif %}
6270
end
6371
end

lib/line/bot/v2/channel_access_token/model/channel_access_token_key_ids_response.rb

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,30 @@ def initialize(
2121
**dynamic_attributes
2222
)
2323

24-
@kids = kids
24+
@kids = kids.map do |item|
25+
if item.is_a?(Hash)
26+
Line::Bot::V2::ChannelAccessToken::string.create(**item)
27+
else
28+
item
29+
end
30+
end
2531

2632
dynamic_attributes.each do |key, value|
2733
self.class.attr_accessor key
28-
instance_variable_set("@#{key}", value)
34+
35+
if value.is_a?(Hash)
36+
struct_klass = Struct.new(*value.keys.map(&:to_sym))
37+
struct_values = value.map { |_k, v| v.is_a?(Hash) ? Line::Bot::V2::Utils.hash_to_struct(v) : v }
38+
instance_variable_set("@#{key}", struct_klass.new(*struct_values))
39+
else
40+
instance_variable_set("@#{key}", value)
41+
end
2942
end
3043
end
44+
45+
def self.create(args)
46+
return new(**args)
47+
end
3148
end
3249
end
3350
end

lib/line/bot/v2/channel_access_token/model/error_response.rb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,20 @@ def initialize(
2727

2828
dynamic_attributes.each do |key, value|
2929
self.class.attr_accessor key
30-
instance_variable_set("@#{key}", value)
30+
31+
if value.is_a?(Hash)
32+
struct_klass = Struct.new(*value.keys.map(&:to_sym))
33+
struct_values = value.map { |_k, v| v.is_a?(Hash) ? Line::Bot::V2::Utils.hash_to_struct(v) : v }
34+
instance_variable_set("@#{key}", struct_klass.new(*struct_values))
35+
else
36+
instance_variable_set("@#{key}", value)
37+
end
3138
end
3239
end
40+
41+
def self.create(args)
42+
return new(**args)
43+
end
3344
end
3445
end
3546
end

lib/line/bot/v2/channel_access_token/model/issue_channel_access_token_response.rb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,20 @@ def initialize(
3434

3535
dynamic_attributes.each do |key, value|
3636
self.class.attr_accessor key
37-
instance_variable_set("@#{key}", value)
37+
38+
if value.is_a?(Hash)
39+
struct_klass = Struct.new(*value.keys.map(&:to_sym))
40+
struct_values = value.map { |_k, v| v.is_a?(Hash) ? Line::Bot::V2::Utils.hash_to_struct(v) : v }
41+
instance_variable_set("@#{key}", struct_klass.new(*struct_values))
42+
else
43+
instance_variable_set("@#{key}", value)
44+
end
3845
end
3946
end
47+
48+
def self.create(args)
49+
return new(**args)
50+
end
4051
end
4152
end
4253
end

lib/line/bot/v2/channel_access_token/model/issue_short_lived_channel_access_token_response.rb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,20 @@ def initialize(
3131

3232
dynamic_attributes.each do |key, value|
3333
self.class.attr_accessor key
34-
instance_variable_set("@#{key}", value)
34+
35+
if value.is_a?(Hash)
36+
struct_klass = Struct.new(*value.keys.map(&:to_sym))
37+
struct_values = value.map { |_k, v| v.is_a?(Hash) ? Line::Bot::V2::Utils.hash_to_struct(v) : v }
38+
instance_variable_set("@#{key}", struct_klass.new(*struct_values))
39+
else
40+
instance_variable_set("@#{key}", value)
41+
end
3542
end
3643
end
44+
45+
def self.create(args)
46+
return new(**args)
47+
end
3748
end
3849
end
3950
end

lib/line/bot/v2/channel_access_token/model/issue_stateless_channel_access_token_response.rb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,20 @@ def initialize(
3131

3232
dynamic_attributes.each do |key, value|
3333
self.class.attr_accessor key
34-
instance_variable_set("@#{key}", value)
34+
35+
if value.is_a?(Hash)
36+
struct_klass = Struct.new(*value.keys.map(&:to_sym))
37+
struct_values = value.map { |_k, v| v.is_a?(Hash) ? Line::Bot::V2::Utils.hash_to_struct(v) : v }
38+
instance_variable_set("@#{key}", struct_klass.new(*struct_values))
39+
else
40+
instance_variable_set("@#{key}", value)
41+
end
3542
end
3643
end
44+
45+
def self.create(args)
46+
return new(**args)
47+
end
3748
end
3849
end
3950
end

lib/line/bot/v2/channel_access_token/model/verify_channel_access_token_response.rb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,20 @@ def initialize(
3030

3131
dynamic_attributes.each do |key, value|
3232
self.class.attr_accessor key
33-
instance_variable_set("@#{key}", value)
33+
34+
if value.is_a?(Hash)
35+
struct_klass = Struct.new(*value.keys.map(&:to_sym))
36+
struct_values = value.map { |_k, v| v.is_a?(Hash) ? Line::Bot::V2::Utils.hash_to_struct(v) : v }
37+
instance_variable_set("@#{key}", struct_klass.new(*struct_values))
38+
else
39+
instance_variable_set("@#{key}", value)
40+
end
3441
end
3542
end
43+
44+
def self.create(args)
45+
return new(**args)
46+
end
3647
end
3748
end
3849
end

0 commit comments

Comments
 (0)