trino-client 2.0.0 → 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,117 +0,0 @@
1
- if ARGV.length != 4
2
- puts "usage: <model-version> <trino-source-dir> <template.erb> <output.rb>"
3
- exit 1
4
- end
5
-
6
- model_version, source_dir, template_path, output_path = *ARGV
7
-
8
- require_relative 'trino_models'
9
-
10
- require 'erb'
11
- erb = ERB.new(File.read(template_path))
12
-
13
- source_path = source_dir
14
-
15
- predefined_simple_classes = %w[StageId TaskId Lifespan ConnectorSession ResourceGroupId]
16
- predefined_models = %w[DistributionSnapshot PlanNode EquiJoinClause WriterTarget WriteStatisticsTarget OperatorInfo HashCollisionsInfo]
17
-
18
- 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]
19
- 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]
20
-
21
- root_models = %w[QueryResults QueryInfo BasicQueryInfo] + %w[
22
- OutputNode
23
- ProjectNode
24
- TableScanNode
25
- ValuesNode
26
- AggregationNode
27
- MarkDistinctNode
28
- FilterNode
29
- WindowNode
30
- RowNumberNode
31
- TopNRowNumberNode
32
- LimitNode
33
- DistinctLimitNode
34
- TopNNode
35
- SampleNode
36
- SortNode
37
- RemoteSourceNode
38
- JoinNode
39
- SemiJoinNode
40
- SpatialJoinNode
41
- IndexJoinNode
42
- IndexSourceNode
43
- TableWriterNode
44
- DeleteNode
45
- TableFinishNode
46
- UnnestNode
47
- ExchangeNode
48
- UnionNode
49
- IntersectNode
50
- EnforceSingleRowNode
51
- GroupIdNode
52
- ExplainAnalyzeNode
53
- ApplyNode
54
- AssignUniqueId
55
- CorrelatedJoinNode
56
- StatisticsWriterNode
57
- ] + %w[
58
- ExchangeClientStatus
59
- LocalExchangeBufferInfo
60
- TableFinishInfo
61
- SplitOperatorInfo
62
- PartitionedOutputInfo
63
- JoinOperatorInfo
64
- WindowInfo
65
- TableWriterInfo
66
- ]
67
-
68
- name_mapping = Hash[*%w[
69
- StatementStats StageStats ClientStageStats
70
- ClientStageStats StageStats ClientStageStats
71
- QueryResults Column ClientColumn
72
- ].each_slice(3).map { |x, y, z| [[x, y], z] }.flatten(1)]
73
-
74
- path_mapping = Hash[*%w[
75
- ClientColumn client/trino-client/src/main/java/io/trino/client/Column.java
76
- ClientStageStats client/trino-client/src/main/java/io/trino/client/StageStats.java
77
- Column core/trino-main/src/main/java/io/trino/execution/Column.java
78
- QueryStats core/trino-main/src/main/java/io/trino/execution/QueryStats.java
79
- StageStats core/trino-main/src/main/java/io/trino/execution/StageStats.java
80
- PartitionedOutputInfo core/trino-main/src/main/java/io/trino/operator/PartitionedOutputOperator.java
81
- TableWriterInfo core/trino-main/src/main/java/io/trino/operator/TableWriterOperator.java
82
- TableInfo core/trino-main/src/main/java/io/trino/execution/TableInfo.java
83
- DynamicFiltersStats core/trino-main/src/main/java/io/trino/server/DynamicFilterService.java
84
- ].map.with_index { |v, i| (i % 2 == 0) ? v : (source_path + "/" + v) }]
85
-
86
- # model => [ [key,nullable,type], ... ]
87
- extra_fields = {
88
- 'QueryInfo' => [['finalQueryInfo', nil, 'boolean']]
89
- }
90
-
91
- analyzer = TrinoModels::ModelAnalyzer.new(
92
- source_path,
93
- skip_models: predefined_models + predefined_simple_classes + assume_primitive + enum_types,
94
- path_mapping: path_mapping,
95
- name_mapping: name_mapping,
96
- extra_fields: extra_fields
97
- )
98
- analyzer.analyze(root_models)
99
- models = analyzer.models
100
- skipped_models = analyzer.skipped_models
101
-
102
- formatter = TrinoModels::ModelFormatter.new(
103
- base_indent_count: 2,
104
- struct_class: "Base",
105
- special_struct_initialize_method: "initialize_struct",
106
- primitive_types: assume_primitive,
107
- skip_types: skipped_models,
108
- simple_classes: predefined_simple_classes,
109
- enum_types: enum_types
110
- )
111
- formatter.format(models)
112
-
113
- @contents = formatter.contents
114
- @model_version = model_version
115
-
116
- data = erb.result
117
- File.write(output_path, data)
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,268 +0,0 @@
1
- module TrinoModels
2
- require 'find'
3
- require 'stringio'
4
-
5
- PRIMITIVE_TYPES = %w[String boolean long int short byte double float Integer Double Boolean]
6
- ARRAY_PRIMITIVE_TYPES = PRIMITIVE_TYPES.map { |t| "#{t}[]" }
7
-
8
- class Model < Struct.new(:name, :fields)
9
- end
10
-
11
- class Field < Struct.new(:key, :nullable, :array, :map, :type, :base_type, :map_value_base_type, :base_type_alias)
12
- alias_method :nullable?, :nullable
13
- alias_method :array?, :array
14
- alias_method :map?, :map
15
-
16
- def name
17
- @name ||= key.gsub(/[A-Z]/) { |f| "_#{f.downcase}" }
18
- end
19
- end
20
-
21
- class ModelAnalysisError < StandardError
22
- end
23
-
24
- class ModelAnalyzer
25
- def initialize(source_path, options = {})
26
- @source_path = source_path
27
- @ignore_types = PRIMITIVE_TYPES + ARRAY_PRIMITIVE_TYPES + (options[:skip_models] || [])
28
- @path_mapping = options[:path_mapping] || {}
29
- @name_mapping = options[:name_mapping] || {}
30
- @extra_fields = options[:extra_fields] || {}
31
- @models = {}
32
- @skipped_models = []
33
- end
34
-
35
- attr_reader :skipped_models
36
-
37
- def models
38
- @models.values.sort_by { |model| model.name }
39
- end
40
-
41
- def analyze(root_models)
42
- root_models.each { |model_name|
43
- analyze_model(model_name)
44
- }
45
- end
46
-
47
- private
48
-
49
- PROPERTY_PATTERN = /@JsonProperty\(\"(\w+)\"\)\s+(@Nullable\s+)?([\w\<\>\[\]\,\s\.]+)\s+\w+/
50
- CREATOR_PATTERN = /@JsonCreator[\s]+public[\s]+(static\s+)?(\w+)[\w\s]*\((?:\s*#{PROPERTY_PATTERN}\s*,?)+\)/
51
- GENERIC_PATTERN = /(\w+)\<(\w+)\>/
52
-
53
- def analyze_fields(model_name, creator_block, generic: nil)
54
- model_name = "#{model_name}_#{generic}" if generic
55
- extra = @extra_fields[model_name] || []
56
- fields = creator_block.scan(PROPERTY_PATTERN).concat(extra).map do |key, nullable, type|
57
- map = false
58
- array = false
59
- nullable = !!nullable
60
- if m = /(?:List|Set)<(\w+)>/.match(type)
61
- base_type = m[1]
62
- array = true
63
- elsif m = /(?:Map|ListMultimap)<(\w+),\s*(\w+)>/.match(type)
64
- base_type = m[1]
65
- map_value_base_type = m[2]
66
- map = true
67
- elsif m = /Optional<([\w\[\]\<\>]+)>/.match(type)
68
- base_type = m[1]
69
- nullable = true
70
- elsif m = /OptionalInt/.match(type)
71
- base_type = 'Integer'
72
- nullable = true
73
- elsif m = /OptionalLong/.match(type)
74
- base_type = 'Long'
75
- nullable = true
76
- elsif m = /OptionalDouble/.match(type)
77
- base_type = 'Double'
78
- nullable = true
79
- elsif type =~ /\w+/
80
- base_type = type
81
- else
82
- raise ModelAnalysisError, "Unsupported type #{type} in model #{model_name}"
83
- end
84
- base_type = @name_mapping[[model_name, base_type]] || base_type
85
- map_value_base_type = @name_mapping[[model_name, map_value_base_type]] || map_value_base_type
86
-
87
- if generic
88
- base_type = generic if base_type == 'T'
89
- map_value_base_type = generic if map_value_base_type == 'T'
90
- end
91
- if m = GENERIC_PATTERN.match(base_type)
92
- base_type_alias = "#{m[1]}_#{m[2]}"
93
- end
94
-
95
- Field.new(key, !!nullable, array, map, type, base_type, map_value_base_type, base_type_alias)
96
- end
97
-
98
- @models[model_name] = Model.new(model_name, fields)
99
- # recursive call
100
- fields.each do |field|
101
- analyze_model(field.base_type, model_name)
102
- analyze_model(field.map_value_base_type, model_name) if field.map_value_base_type
103
- end
104
-
105
- fields
106
- end
107
-
108
- def analyze_model(model_name, parent_model = nil, generic: nil)
109
- return if @models[model_name] || @ignore_types.include?(model_name)
110
-
111
- if m = GENERIC_PATTERN.match(model_name)
112
- analyze_model(m[1], generic: m[2])
113
- analyze_model(m[2])
114
- return
115
- end
116
-
117
- path = find_class_file(model_name, parent_model)
118
- java = File.read(path)
119
-
120
- m = CREATOR_PATTERN.match(java)
121
- unless m
122
- raise ModelAnalysisError, "Can't find JsonCreator of a model class #{model_name} of #{parent_model} at #{path}"
123
- end
124
-
125
- body = m[0]
126
- # check inner class first
127
- while true
128
- offset = m.end(0)
129
- m = CREATOR_PATTERN.match(java, offset)
130
- break unless m
131
- inner_model_name = m[2]
132
- next if @models[inner_model_name] || @ignore_types.include?(inner_model_name)
133
- fields = analyze_fields(inner_model_name, m[0])
134
- end
135
-
136
- fields = analyze_fields(model_name, body, generic: generic)
137
-
138
- rescue => e
139
- puts "Skipping model #{parent_model}/#{model_name}: #{e}"
140
- @skipped_models << model_name
141
- end
142
-
143
- def find_class_file(model_name, parent_model)
144
- return @path_mapping[model_name] if @path_mapping.has_key? model_name
145
-
146
- @source_files ||= Find.find(@source_path).to_a
147
- pattern = /\/#{model_name}.java$/
148
- matched = @source_files.find_all { |path| path =~ pattern && !path.include?('/test/') && !path.include?('/verifier/') }
149
- if matched.empty?
150
- raise ModelAnalysisError, "Model class #{model_name} is not found"
151
- end
152
- if matched.size == 1
153
- matched.first
154
- else
155
- raise ModelAnalysisError, "Model class #{model_name} of #{parent_model} found multiple match #{matched}"
156
- end
157
- end
158
- end
159
-
160
- class ModelFormatter
161
- def initialize(options = {})
162
- @indent = options[:indent] || ' '
163
- @base_indent_count = options[:base_indent_count] || 0
164
- @struct_class = options[:struct_class] || 'Struct'
165
- @special_struct_initialize_method = options[:special_struct_initialize_method]
166
- @primitive_types = PRIMITIVE_TYPES + ARRAY_PRIMITIVE_TYPES + (options[:primitive_types] || [])
167
- @skip_types = options[:skip_types] || []
168
- @simple_classes = options[:simple_classes]
169
- @enum_types = options[:enum_types]
170
- @special_types = options[:special_types] || {}
171
- @data = StringIO.new
172
- end
173
-
174
- def contents
175
- @data.string
176
- end
177
-
178
- def format(models)
179
- @models = models
180
- models.each do |model|
181
- @model = model
182
-
183
- puts_with_indent 0, "class << #{model.name} ="
184
- puts_with_indent 2, "#{@struct_class}.new(#{model.fields.map { |f| ":#{f.name}" }.join(', ')})"
185
- format_decode
186
- puts_with_indent 0, "end"
187
- line
188
- end
189
- end
190
-
191
- private
192
-
193
- def line
194
- @data.puts ""
195
- end
196
-
197
- def puts_with_indent(n, str)
198
- @data.puts "#{@indent * (@base_indent_count + n)}#{str}"
199
- end
200
-
201
- def format_decode
202
- puts_with_indent 1, "def decode(hash)"
203
-
204
- puts_with_indent 2, "unless hash.is_a?(Hash)"
205
- puts_with_indent 3, "raise TypeError, \"Can't convert \#{hash.class} to Hash\""
206
- puts_with_indent 2, "end"
207
-
208
- if @special_struct_initialize_method
209
- puts_with_indent 2, "obj = allocate"
210
- puts_with_indent 2, "obj.send(:#{@special_struct_initialize_method},"
211
- else
212
- puts_with_indent 2, "new("
213
- end
214
-
215
- @model.fields.each do |field|
216
- next if @skip_types.include?(field.base_type) || @skip_types.include?(field.map_value_base_type)
217
-
218
- if @primitive_types.include?(field.base_type) && !field.map?
219
- expr = "hash[\"#{field.key}\"]"
220
- else
221
- expr = ""
222
- expr << "hash[\"#{field.key}\"] && " # if field.nullable?
223
-
224
- if field.map?
225
- key_expr = convert_expression(field.base_type, field.base_type, "k")
226
- value_expr = convert_expression(field.map_value_base_type, field.map_value_base_type, "v")
227
- if key_expr == 'k' && value_expr == 'v'
228
- expr = "hash[\"#{field.key}\"]"
229
- else
230
- expr << "Hash[hash[\"#{field.key}\"].to_a.map! {|k,v| [#{key_expr}, #{value_expr}] }]"
231
- end
232
- elsif field.array?
233
- elem_expr = convert_expression(field.base_type, field.base_type, "h")
234
- expr << "hash[\"#{field.key}\"].map {|h| #{elem_expr} }"
235
- else
236
- expr << convert_expression(field.type, field.base_type_alias || field.base_type, "hash[\"#{field.key}\"]")
237
- end
238
- end
239
-
240
- # comment = "# #{field.base_type}#{field.array? ? '[]' : ''} #{field.key}"
241
- # puts_with_indent 3, "#{expr}, #{comment}"
242
- puts_with_indent 3, "#{expr},"
243
- end
244
-
245
- puts_with_indent 2, ")"
246
-
247
- if @special_struct_initialize_method
248
- puts_with_indent 2, "obj"
249
- end
250
-
251
- puts_with_indent 1, "end"
252
- end
253
-
254
- def convert_expression(type, base_type, key)
255
- if @special_types[type]
256
- special.call(key)
257
- elsif @enum_types.include?(type) || @enum_types.include?(base_type)
258
- "#{key}.downcase.to_sym"
259
- elsif @primitive_types.include?(base_type)
260
- key
261
- elsif @simple_classes.include?(base_type)
262
- "#{base_type}.new(#{key})"
263
- else # model class
264
- "#{base_type}.decode(#{key})"
265
- end
266
- end
267
- end
268
- end