trino-client 1.0.2 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,280 +0,0 @@
1
- #
2
- # Trino client for Ruby
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- #
16
- module Trino::Client::ModelVersions
17
-
18
- ####
19
- ## lib/trino/client/model_versions/*.rb is automatically generated using "rake modelgen:all" command.
20
- ## You should not edit this file directly. To modify the class definitions, edit
21
- ## modelgen/model_versions.rb file and run "rake modelgen:all".
22
- ##
23
-
24
- module V<%= @model_version.gsub(".", "_") %>
25
- class Base < Struct
26
- class << self
27
- alias_method :new_struct, :new
28
-
29
- def new(*args)
30
- new_struct(*args) do
31
- # make it immutable
32
- undef_method :"[]="
33
- members.each do |m|
34
- undef_method :"#{m}="
35
- end
36
-
37
- # replace constructor to receive hash instead of array
38
- alias_method :initialize_struct, :initialize
39
-
40
- def initialize(params={})
41
- initialize_struct(*members.map {|m| params[m] })
42
- end
43
- end
44
- end
45
- end
46
- end
47
-
48
- class StageId < String
49
- def initialize(str)
50
- super
51
- splitted = split('.', 2)
52
- @query_id = splitted[0]
53
- @id = splitted[1]
54
- end
55
-
56
- attr_reader :query_id, :id
57
- end
58
-
59
- class TaskId < String
60
- def initialize(str)
61
- super
62
- splitted = split('.', 3)
63
- @stage_id = StageId.new("#{splitted[0]}.#{splitted[1]}")
64
- @query_id = @stage_id.query_id
65
- @id = splitted[2]
66
- end
67
-
68
- attr_reader :query_id, :stage_id, :id
69
- end
70
-
71
- class Lifespan < String
72
- def initialize(str)
73
- super
74
- if str == "TaskWide"
75
- @grouped = false
76
- @group_id = 0
77
- else
78
- # Group1
79
- @grouped = true
80
- @group_id = str[5..-1].to_i
81
- end
82
- end
83
-
84
- attr_reader :grouped, :group_id
85
- end
86
-
87
- class ConnectorSession < Hash
88
- def initialize(hash)
89
- super()
90
- merge!(hash)
91
- end
92
- end
93
-
94
- module PlanNode
95
- def self.decode(hash)
96
- unless hash.is_a?(Hash)
97
- raise TypeError, "Can't convert #{hash.class} to Hash"
98
- end
99
- model_class = case hash["@type"]
100
- when "output" then OutputNode
101
- when "project" then ProjectNode
102
- when "tablescan" then TableScanNode
103
- when "values" then ValuesNode
104
- when "aggregation" then AggregationNode
105
- when "markDistinct" then MarkDistinctNode
106
- when "filter" then FilterNode
107
- when "window" then WindowNode
108
- when "rowNumber" then RowNumberNode
109
- when "topnRowNumber" then TopNRowNumberNode
110
- when "limit" then LimitNode
111
- when "distinctlimit" then DistinctLimitNode
112
- when "topn" then TopNNode
113
- when "sample" then SampleNode
114
- when "sort" then SortNode
115
- when "remoteSource" then RemoteSourceNode
116
- when "join" then JoinNode
117
- when "semijoin" then SemiJoinNode
118
- when "spatialjoin" then SpatialJoinNode
119
- when "indexjoin" then IndexJoinNode
120
- when "indexsource" then IndexSourceNode
121
- when "tablewriter" then TableWriterNode
122
- when "delete" then DeleteNode
123
- when "metadatadelete" then MetadataDeleteNode
124
- when "tablecommit" then TableFinishNode
125
- when "unnest" then UnnestNode
126
- when "exchange" then ExchangeNode
127
- when "union" then UnionNode
128
- when "intersect" then IntersectNode
129
- when "scalar" then EnforceSingleRowNode
130
- when "groupid" then GroupIdNode
131
- when "explainAnalyze" then ExplainAnalyzeNode
132
- when "apply" then ApplyNode
133
- when "assignUniqueId" then AssignUniqueId
134
- when "correlatedJoin" then CorrelatedJoinNode
135
- when "statisticsWriterNode" then StatisticsWriterNode
136
- end
137
- if model_class
138
- node = model_class.decode(hash)
139
- class << node
140
- attr_accessor :plan_node_type
141
- end
142
- node.plan_node_type = hash['@type']
143
- node
144
- end
145
- end
146
- end
147
-
148
- # io.airlift.stats.Distribution.DistributionSnapshot
149
- class << DistributionSnapshot =
150
- Base.new(:max_error, :count, :total, :p01, :p05, :p10, :p25, :p50, :p75, :p90, :p95, :p99, :min, :max)
151
- def decode(hash)
152
- unless hash.is_a?(Hash)
153
- raise TypeError, "Can't convert #{hash.class} to Hash"
154
- end
155
- obj = allocate
156
- obj.send(:initialize_struct,
157
- hash["maxError"],
158
- hash["count"],
159
- hash["total"],
160
- hash["p01"],
161
- hash["p05"],
162
- hash["p10"],
163
- hash["p25"],
164
- hash["p50"],
165
- hash["p75"],
166
- hash["p90"],
167
- hash["p95"],
168
- hash["p99"],
169
- hash["min"],
170
- hash["max"],
171
- )
172
- obj
173
- end
174
- end
175
-
176
- # This is a hybrid of JoinNode.EquiJoinClause and IndexJoinNode.EquiJoinClause
177
- class << EquiJoinClause =
178
- Base.new(:left, :right, :probe, :index)
179
- def decode(hash)
180
- unless hash.is_a?(Hash)
181
- raise TypeError, "Can't convert #{hash.class} to Hash"
182
- end
183
- obj = allocate
184
- obj.send(:initialize_struct,
185
- hash["left"],
186
- hash["right"],
187
- hash["probe"],
188
- hash["index"],
189
- )
190
- obj
191
- end
192
- end
193
-
194
- class << WriterTarget =
195
- Base.new(:type, :handle)
196
- def decode(hash)
197
- unless hash.is_a?(Hash)
198
- raise TypeError, "Can't convert #{hash.class} to Hash"
199
- end
200
- obj = allocate
201
- model_class = case hash["@type"]
202
- when "CreateTarget" then CreateTarget
203
- when "InsertTarget" then InsertTarget
204
- when "DeleteTarget" then DeleteTarget
205
- end
206
- if model_class
207
- model_class.decode(hash)
208
- end
209
- end
210
- end
211
-
212
- class << WriteStatisticsTarget =
213
- Base.new(:type, :handle)
214
- def decode(hash)
215
- unless hash.is_a?(Hash)
216
- raise TypeError, "Can't convert #{hash.class} to Hash"
217
- end
218
- obj = allocate
219
- model_class = case hash["@type"]
220
- when "WriteStatisticsHandle" then WriteStatisticsHandle
221
- end
222
- if model_class
223
- model_class.decode(hash)
224
- end
225
- end
226
- end
227
-
228
- # Inner classes
229
- module OperatorInfo
230
- def self.decode(hash)
231
- unless hash.is_a?(Hash)
232
- raise TypeError, "Can't convert #{hash.class} to Hash"
233
- end
234
- model_class = case hash["@type"]
235
- when "exchangeClientStatus" then ExchangeClientStatus
236
- when "localExchangeBuffer" then LocalExchangeBufferInfo
237
- when "tableFinish" then TableFinishInfo
238
- when "splitOperator" then SplitOperatorInfo
239
- when "hashCollisionsInfo" then HashCollisionsInfo
240
- when "partitionedOutput" then PartitionedOutputInfo
241
- when "joinOperatorInfo" then JoinOperatorInfo
242
- when "windowInfo" then WindowInfo
243
- when "tableWriter" then TableWriterInfo
244
- end
245
- if model_class
246
- model_class.decode(hash)
247
- end
248
- end
249
- end
250
-
251
- class << HashCollisionsInfo =
252
- Base.new(:weighted_hash_collisions, :weighted_sum_squared_hash_collisions, :weighted_expectedHash_collisions)
253
- def decode(hash)
254
- unless hash.is_a?(Hash)
255
- raise TypeError, "Can't convert #{hash.class} to Hash"
256
- end
257
- obj = allocate
258
- obj.send(:initialize_struct,
259
- hash["weighted_hash_collisions"],
260
- hash["weighted_sum_squared_hash_collisions"],
261
- hash["weighted_expectedHash_collisions"]
262
- )
263
- obj
264
- end
265
- end
266
-
267
- class ResourceGroupId < Array
268
- def initialize(array)
269
- super()
270
- concat(array)
271
- end
272
- end
273
-
274
- ##
275
- # Those model classes are automatically generated
276
- #
277
-
278
- <%= @contents %>
279
- end
280
- end
data/modelgen/modelgen.rb DELETED
@@ -1,119 +0,0 @@
1
-
2
- if ARGV.length != 4
3
- puts "usage: <model-version> <trino-source-dir> <template.erb> <output.rb>"
4
- exit 1
5
- end
6
-
7
- model_version, source_dir, template_path, output_path = *ARGV
8
-
9
- require_relative 'trino_models'
10
-
11
- require 'erb'
12
- erb = ERB.new(File.read(template_path))
13
-
14
- source_path = source_dir
15
-
16
- predefined_simple_classes = %w[StageId TaskId Lifespan ConnectorSession ResourceGroupId]
17
- predefined_models = %w[DistributionSnapshot PlanNode EquiJoinClause WriterTarget WriteStatisticsTarget OperatorInfo HashCollisionsInfo]
18
-
19
- assume_primitive = %w[Object Type Long Symbol QueryId PlanNodeId PlanFragmentId MemoryPoolId TransactionId URI Duration DataSize DateTime ColumnHandle ConnectorTableHandle ConnectorOutputTableHandle ConnectorIndexHandle ConnectorColumnHandle ConnectorInsertTableHandle ConnectorTableLayoutHandle Expression FunctionCall TimeZoneKey Locale TypeSignature Frame TupleDomain<ColumnHandle> SerializableNativeValue ConnectorTransactionHandle OutputBufferId ConnectorPartitioningHandle NullableValue ConnectorId HostAddress JsonNode Node CatalogName QualifiedObjectName FunctionId DynamicFilterId Instant]
20
- enum_types = %w[QueryState StageState TaskState QueueState PlanDistribution OutputPartitioning Step SortOrder BufferState NullPartitioning BlockedReason ParameterKind FunctionKind PartitionFunctionHandle Scope ErrorType DistributionType PipelineExecutionStrategy JoinType ExchangeNode.Type ColumnStatisticType TableStatisticType StageExecutionStrategy SemanticErrorCode QueryType]
21
-
22
- root_models = %w[QueryResults QueryInfo BasicQueryInfo] + %w[
23
- OutputNode
24
- ProjectNode
25
- TableScanNode
26
- ValuesNode
27
- AggregationNode
28
- MarkDistinctNode
29
- FilterNode
30
- WindowNode
31
- RowNumberNode
32
- TopNRowNumberNode
33
- LimitNode
34
- DistinctLimitNode
35
- TopNNode
36
- SampleNode
37
- SortNode
38
- RemoteSourceNode
39
- JoinNode
40
- SemiJoinNode
41
- SpatialJoinNode
42
- IndexJoinNode
43
- IndexSourceNode
44
- TableWriterNode
45
- DeleteNode
46
- TableFinishNode
47
- UnnestNode
48
- ExchangeNode
49
- UnionNode
50
- IntersectNode
51
- EnforceSingleRowNode
52
- GroupIdNode
53
- ExplainAnalyzeNode
54
- ApplyNode
55
- AssignUniqueId
56
- CorrelatedJoinNode
57
- StatisticsWriterNode
58
- ] + %w[
59
- ExchangeClientStatus
60
- LocalExchangeBufferInfo
61
- TableFinishInfo
62
- SplitOperatorInfo
63
- PartitionedOutputInfo
64
- JoinOperatorInfo
65
- WindowInfo
66
- TableWriterInfo
67
- ]
68
-
69
- name_mapping = Hash[*%w[
70
- StatementStats StageStats ClientStageStats
71
- ClientStageStats StageStats ClientStageStats
72
- QueryResults Column ClientColumn
73
- ].each_slice(3).map { |x, y, z| [[x,y], z] }.flatten(1)]
74
-
75
- path_mapping = Hash[*%w[
76
- ClientColumn client/trino-client/src/main/java/io/trino/client/Column.java
77
- ClientStageStats client/trino-client/src/main/java/io/trino/client/StageStats.java
78
- Column core/trino-main/src/main/java/io/trino/execution/Column.java
79
- QueryStats core/trino-main/src/main/java/io/trino/execution/QueryStats.java
80
- StageStats core/trino-main/src/main/java/io/trino/execution/StageStats.java
81
- PartitionedOutputInfo core/trino-main/src/main/java/io/trino/operator/PartitionedOutputOperator.java
82
- TableWriterInfo core/trino-main/src/main/java/io/trino/operator/TableWriterOperator.java
83
- TableInfo core/trino-main/src/main/java/io/trino/execution/TableInfo.java
84
- DynamicFiltersStats core/trino-main/src/main/java/io/trino/server/DynamicFilterService.java
85
- ].map.with_index { |v,i| i % 2 == 0 ? v : (source_path + "/" + v) }]
86
-
87
- # model => [ [key,nullable,type], ... ]
88
- extra_fields = {
89
- 'QueryInfo' => [['finalQueryInfo', nil, 'boolean']]
90
- }
91
-
92
- analyzer = TrinoModels::ModelAnalyzer.new(
93
- source_path,
94
- skip_models: predefined_models + predefined_simple_classes + assume_primitive + enum_types,
95
- path_mapping: path_mapping,
96
- name_mapping: name_mapping,
97
- extra_fields: extra_fields
98
- )
99
- analyzer.analyze(root_models)
100
- models = analyzer.models
101
- skipped_models = analyzer.skipped_models
102
-
103
- formatter = TrinoModels::ModelFormatter.new(
104
- base_indent_count: 2,
105
- struct_class: "Base",
106
- special_struct_initialize_method: "initialize_struct",
107
- primitive_types: assume_primitive,
108
- skip_types: skipped_models,
109
- simple_classes: predefined_simple_classes,
110
- enum_types: enum_types,
111
- )
112
- formatter.format(models)
113
-
114
- @contents = formatter.contents
115
- @model_version = model_version
116
-
117
- data = erb.result
118
- File.write(output_path, data)
119
-
data/modelgen/models.rb DELETED
@@ -1,31 +0,0 @@
1
- #
2
- # Trino client for Ruby
3
- #
4
- # Licensed under the Apache License, Version 2.0 (the "License");
5
- # you may not use this file except in compliance with the License.
6
- # You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- # Unless required by applicable law or agreed to in writing, software
11
- # distributed under the License is distributed on an "AS IS" BASIS,
12
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- # See the License for the specific language governing permissions and
14
- # limitations under the License.
15
- #
16
- module Trino::Client
17
-
18
- ####
19
- ## lib/trino/client/models.rb is automatically generated using "rake modelgen:latest" command.
20
- ## You should not edit this file directly. To modify the class definitions, edit
21
- ## modelgen/models.rb file and run "rake modelgen:latest".
22
- ##
23
-
24
- module ModelVersions
25
- end
26
- <% @versions.each do |ver| %>
27
- require 'trino/client/model_versions/<%= ver %>.rb'<% end %>
28
-
29
- Models = ModelVersions::V<%= @latest_version.gsub(".", "_") %>
30
-
31
- end
@@ -1,270 +0,0 @@
1
-
2
- module TrinoModels
3
- require 'find'
4
- require 'stringio'
5
-
6
- PRIMITIVE_TYPES = %w[String boolean long int short byte double float Integer Double Boolean]
7
- ARRAY_PRIMITIVE_TYPES = PRIMITIVE_TYPES.map { |t| "#{t}[]" }
8
-
9
- class Model < Struct.new(:name, :fields)
10
- end
11
-
12
- class Field < Struct.new(:key, :nullable, :array, :map, :type, :base_type, :map_value_base_type, :base_type_alias)
13
- alias_method :nullable?, :nullable
14
- alias_method :array?, :array
15
- alias_method :map?, :map
16
-
17
- def name
18
- @name ||= key.gsub(/[A-Z]/) {|f| "_#{f.downcase}" }
19
- end
20
- end
21
-
22
- class ModelAnalysisError < StandardError
23
- end
24
-
25
- class ModelAnalyzer
26
- def initialize(source_path, options={})
27
- @source_path = source_path
28
- @ignore_types = PRIMITIVE_TYPES + ARRAY_PRIMITIVE_TYPES + (options[:skip_models] || [])
29
- @path_mapping = options[:path_mapping] || {}
30
- @name_mapping = options[:name_mapping] || {}
31
- @extra_fields = options[:extra_fields] || {}
32
- @models = {}
33
- @skipped_models = []
34
- end
35
-
36
- attr_reader :skipped_models
37
-
38
- def models
39
- @models.values.sort_by {|model| model.name }
40
- end
41
-
42
- def analyze(root_models)
43
- root_models.each {|model_name|
44
- analyze_model(model_name)
45
- }
46
- end
47
-
48
- private
49
-
50
- PROPERTY_PATTERN = /@JsonProperty\(\"(\w+)\"\)\s+(@Nullable\s+)?([\w\<\>\[\]\,\s\.]+)\s+\w+/
51
- CREATOR_PATTERN = /@JsonCreator[\s]+public[\s]+(static\s+)?(\w+)[\w\s]*\((?:\s*#{PROPERTY_PATTERN}\s*,?)+\)/
52
- GENERIC_PATTERN = /(\w+)\<(\w+)\>/
53
-
54
- def analyze_fields(model_name, creator_block, generic: nil)
55
- model_name = "#{model_name}_#{generic}" if generic
56
- extra = @extra_fields[model_name] || []
57
- fields = creator_block.scan(PROPERTY_PATTERN).concat(extra).map do |key,nullable,type|
58
- map = false
59
- array = false
60
- nullable = !!nullable
61
- if m = /(?:List|Set)<(\w+)>/.match(type)
62
- base_type = m[1]
63
- array = true
64
- elsif m = /(?:Map|ListMultimap)<(\w+),\s*(\w+)>/.match(type)
65
- base_type = m[1]
66
- map_value_base_type = m[2]
67
- map = true
68
- elsif m = /Optional<([\w\[\]\<\>]+)>/.match(type)
69
- base_type = m[1]
70
- nullable = true
71
- elsif m = /OptionalInt/.match(type)
72
- base_type = 'Integer'
73
- nullable = true
74
- elsif m = /OptionalLong/.match(type)
75
- base_type = 'Long'
76
- nullable = true
77
- elsif m = /OptionalDouble/.match(type)
78
- base_type = 'Double'
79
- nullable = true
80
- elsif type =~ /\w+/
81
- base_type = type
82
- else
83
- raise ModelAnalysisError, "Unsupported type #{type} in model #{model_name}"
84
- end
85
- base_type = @name_mapping[[model_name, base_type]] || base_type
86
- map_value_base_type = @name_mapping[[model_name, map_value_base_type]] || map_value_base_type
87
-
88
- if generic
89
- base_type = generic if base_type == 'T'
90
- map_value_base_type = generic if map_value_base_type == 'T'
91
- end
92
- if m = GENERIC_PATTERN.match(base_type)
93
- base_type_alias = "#{m[1]}_#{m[2]}"
94
- end
95
-
96
- Field.new(key, !!nullable, array, map, type, base_type, map_value_base_type, base_type_alias)
97
- end
98
-
99
- @models[model_name] = Model.new(model_name, fields)
100
- # recursive call
101
- fields.each do |field|
102
- analyze_model(field.base_type, model_name)
103
- analyze_model(field.map_value_base_type, model_name) if field.map_value_base_type
104
- end
105
-
106
- return fields
107
- end
108
-
109
- def analyze_model(model_name, parent_model= nil, generic: nil)
110
- return if @models[model_name] || @ignore_types.include?(model_name)
111
-
112
- if m = GENERIC_PATTERN.match(model_name)
113
- analyze_model(m[1], generic: m[2])
114
- analyze_model(m[2])
115
- return
116
- end
117
-
118
- path = find_class_file(model_name, parent_model)
119
- java = File.read(path)
120
-
121
- m = CREATOR_PATTERN.match(java)
122
- unless m
123
- raise ModelAnalysisError, "Can't find JsonCreator of a model class #{model_name} of #{parent_model} at #{path}"
124
- end
125
-
126
- body = m[0]
127
- # check inner class first
128
- while true
129
- offset = m.end(0)
130
- m = CREATOR_PATTERN.match(java, offset)
131
- break unless m
132
- inner_model_name = m[2]
133
- next if @models[inner_model_name] || @ignore_types.include?(inner_model_name)
134
- fields = analyze_fields(inner_model_name, m[0])
135
- end
136
-
137
- fields = analyze_fields(model_name, body, generic: generic)
138
-
139
- rescue => e
140
- puts "Skipping model #{parent_model}/#{model_name}: #{e}"
141
- @skipped_models << model_name
142
- end
143
-
144
- def find_class_file(model_name, parent_model)
145
- return @path_mapping[model_name] if @path_mapping.has_key? model_name
146
-
147
- @source_files ||= Find.find(@source_path).to_a
148
- pattern = /\/#{model_name}.java$/
149
- matched = @source_files.find_all {|path| path =~ pattern && !path.include?('/test/') && !path.include?('/verifier/')}
150
- if matched.empty?
151
- raise ModelAnalysisError, "Model class #{model_name} is not found"
152
- end
153
- if matched.size == 1
154
- return matched.first
155
- else
156
- raise ModelAnalysisError, "Model class #{model_name} of #{parent_model} found multiple match #{matched}"
157
- end
158
- end
159
- end
160
-
161
- class ModelFormatter
162
- def initialize(options={})
163
- @indent = options[:indent] || ' '
164
- @base_indent_count = options[:base_indent_count] || 0
165
- @struct_class = options[:struct_class] || 'Struct'
166
- @special_struct_initialize_method = options[:special_struct_initialize_method]
167
- @primitive_types = PRIMITIVE_TYPES + ARRAY_PRIMITIVE_TYPES + (options[:primitive_types] || [])
168
- @skip_types = options[:skip_types] || []
169
- @simple_classes = options[:simple_classes]
170
- @enum_types = options[:enum_types]
171
- @special_types = options[:special_types] || {}
172
- @data = StringIO.new
173
- end
174
-
175
- def contents
176
- @data.string
177
- end
178
-
179
- def format(models)
180
- @models = models
181
- models.each do |model|
182
- @model = model
183
-
184
- puts_with_indent 0, "class << #{model.name} ="
185
- puts_with_indent 2, "#{@struct_class}.new(#{model.fields.map {|f| ":#{f.name}" }.join(', ')})"
186
- format_decode
187
- puts_with_indent 0, "end"
188
- line
189
- end
190
- end
191
-
192
- private
193
-
194
- def line
195
- @data.puts ""
196
- end
197
-
198
- def puts_with_indent(n, str)
199
- @data.puts "#{@indent * (@base_indent_count + n)}#{str}"
200
- end
201
-
202
- def format_decode
203
- puts_with_indent 1, "def decode(hash)"
204
-
205
- puts_with_indent 2, "unless hash.is_a?(Hash)"
206
- puts_with_indent 3, "raise TypeError, \"Can't convert \#{hash.class} to Hash\""
207
- puts_with_indent 2, "end"
208
-
209
- if @special_struct_initialize_method
210
- puts_with_indent 2, "obj = allocate"
211
- puts_with_indent 2, "obj.send(:#{@special_struct_initialize_method},"
212
- else
213
- puts_with_indent 2, "new("
214
- end
215
-
216
- @model.fields.each do |field|
217
- next if @skip_types.include?(field.base_type) || @skip_types.include?(field.map_value_base_type)
218
-
219
- if @primitive_types.include?(field.base_type) && !field.map?
220
- expr = "hash[\"#{field.key}\"]"
221
- else
222
- expr = ""
223
- expr << "hash[\"#{field.key}\"] && " #if field.nullable?
224
-
225
- if field.map?
226
- key_expr = convert_expression(field.base_type, field.base_type, "k")
227
- value_expr = convert_expression(field.map_value_base_type, field.map_value_base_type, "v")
228
- if key_expr == 'k' && value_expr == 'v'
229
- expr = "hash[\"#{field.key}\"]"
230
- else
231
- expr << "Hash[hash[\"#{field.key}\"].to_a.map! {|k,v| [#{key_expr}, #{value_expr}] }]"
232
- end
233
- elsif field.array?
234
- elem_expr = convert_expression(field.base_type, field.base_type, "h")
235
- expr << "hash[\"#{field.key}\"].map {|h| #{elem_expr} }"
236
- else
237
- expr << convert_expression(field.type, field.base_type_alias || field.base_type, "hash[\"#{field.key}\"]")
238
- end
239
- end
240
-
241
- #comment = "# #{field.base_type}#{field.array? ? '[]' : ''} #{field.key}"
242
- #puts_with_indent 3, "#{expr}, #{comment}"
243
- puts_with_indent 3, "#{expr},"
244
- end
245
-
246
- puts_with_indent 2, ")"
247
-
248
- if @special_struct_initialize_method
249
- puts_with_indent 2, "obj"
250
- end
251
-
252
- puts_with_indent 1, "end"
253
- end
254
-
255
- def convert_expression(type, base_type, key)
256
- if @special_types[type]
257
- special.call(key)
258
- elsif @enum_types.include?(type) || @enum_types.include?(base_type)
259
- "#{key}.downcase.to_sym"
260
- elsif @primitive_types.include?(base_type)
261
- key
262
- elsif @simple_classes.include?(base_type)
263
- "#{base_type}.new(#{key})"
264
- else # model class
265
- "#{base_type}.decode(#{key})"
266
- end
267
- end
268
- end
269
- end
270
-