aws-sdk-code-generator 0.1.0.pre → 0.2.0.pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. checksums.yaml +5 -5
  2. data/lib/aws-sdk-code-generator.rb +68 -75
  3. data/lib/aws-sdk-code-generator/api.rb +130 -0
  4. data/lib/aws-sdk-code-generator/apply_docs.rb +15 -2
  5. data/lib/aws-sdk-code-generator/client_constructor.rb +39 -0
  6. data/lib/aws-sdk-code-generator/client_operation_documentation.rb +268 -0
  7. data/lib/aws-sdk-code-generator/client_operation_list.rb +148 -0
  8. data/lib/aws-sdk-code-generator/client_response_structure_example.rb +108 -0
  9. data/lib/aws-sdk-code-generator/code_builder.rb +146 -133
  10. data/lib/aws-sdk-code-generator/crosslink.rb +42 -0
  11. data/lib/aws-sdk-code-generator/docstring.rb +199 -0
  12. data/lib/aws-sdk-code-generator/error_list.rb +77 -0
  13. data/lib/aws-sdk-code-generator/errors.rb +2 -0
  14. data/lib/aws-sdk-code-generator/eventstream_example.rb +220 -0
  15. data/lib/aws-sdk-code-generator/gem_builder.rb +19 -25
  16. data/lib/aws-sdk-code-generator/hash_formatter.rb +5 -2
  17. data/lib/aws-sdk-code-generator/helper.rb +77 -61
  18. data/lib/aws-sdk-code-generator/plugin_list.rb +146 -0
  19. data/lib/aws-sdk-code-generator/resource_action.rb +69 -0
  20. data/lib/aws-sdk-code-generator/resource_action_code.rb +57 -0
  21. data/lib/aws-sdk-code-generator/resource_association.rb +37 -0
  22. data/lib/aws-sdk-code-generator/resource_attribute.rb +76 -0
  23. data/lib/aws-sdk-code-generator/resource_batch_action.rb +56 -0
  24. data/lib/aws-sdk-code-generator/resource_batch_action_code.rb +136 -0
  25. data/lib/aws-sdk-code-generator/resource_batch_action_documentation.rb +108 -0
  26. data/lib/aws-sdk-code-generator/resource_batch_builder.rb +212 -0
  27. data/lib/aws-sdk-code-generator/resource_builder.rb +48 -0
  28. data/lib/aws-sdk-code-generator/resource_client_request.rb +62 -0
  29. data/lib/aws-sdk-code-generator/resource_client_request_documentation.rb +81 -0
  30. data/lib/aws-sdk-code-generator/resource_client_request_params.rb +86 -0
  31. data/lib/aws-sdk-code-generator/resource_data_method.rb +60 -0
  32. data/lib/aws-sdk-code-generator/resource_has_association.rb +117 -0
  33. data/lib/aws-sdk-code-generator/resource_has_many_association.rb +52 -0
  34. data/lib/aws-sdk-code-generator/resource_has_many_association_code.rb +76 -0
  35. data/lib/aws-sdk-code-generator/resource_identifier.rb +44 -0
  36. data/lib/aws-sdk-code-generator/resource_identifiers_method.rb +29 -0
  37. data/lib/aws-sdk-code-generator/resource_load_method.rb +68 -0
  38. data/lib/aws-sdk-code-generator/resource_method.rb +22 -0
  39. data/lib/aws-sdk-code-generator/resource_skip_params.rb +36 -0
  40. data/lib/aws-sdk-code-generator/resource_value_source.rb +68 -0
  41. data/lib/aws-sdk-code-generator/resource_waiter.rb +80 -0
  42. data/lib/aws-sdk-code-generator/service.rb +30 -7
  43. data/lib/aws-sdk-code-generator/shared_example.rb +131 -0
  44. data/lib/aws-sdk-code-generator/syntax_example.rb +60 -0
  45. data/lib/aws-sdk-code-generator/syntax_example_hash.rb +174 -0
  46. data/lib/aws-sdk-code-generator/underscore.rb +10 -5
  47. data/lib/aws-sdk-code-generator/view.rb +33 -0
  48. data/lib/aws-sdk-code-generator/views.rb +2 -0
  49. data/lib/aws-sdk-code-generator/views/apig_endpoint_class.rb +25 -0
  50. data/lib/aws-sdk-code-generator/views/apig_readme.rb +32 -0
  51. data/lib/aws-sdk-code-generator/views/async_client_class.rb +68 -0
  52. data/lib/aws-sdk-code-generator/views/authorizer_class.rb +17 -0
  53. data/lib/aws-sdk-code-generator/views/client_api_module.rb +583 -0
  54. data/lib/aws-sdk-code-generator/views/client_class.rb +93 -0
  55. data/lib/aws-sdk-code-generator/views/docstring.rb +27 -0
  56. data/lib/aws-sdk-code-generator/views/errors_module.rb +32 -0
  57. data/lib/aws-sdk-code-generator/views/event_streams_module.rb +149 -0
  58. data/lib/aws-sdk-code-generator/views/features/env.rb +9 -0
  59. data/lib/aws-sdk-code-generator/views/features/smoke.rb +51 -0
  60. data/lib/aws-sdk-code-generator/views/features/smoke_step_definitions.rb +26 -0
  61. data/lib/aws-sdk-code-generator/views/features/step_definitions.rb +2 -0
  62. data/lib/aws-sdk-code-generator/views/gemspec.rb +39 -5
  63. data/lib/aws-sdk-code-generator/views/resource_class.rb +122 -0
  64. data/lib/aws-sdk-code-generator/views/root_resource_class.rb +58 -0
  65. data/lib/aws-sdk-code-generator/views/service_module.rb +30 -14
  66. data/lib/aws-sdk-code-generator/views/spec/spec_helper.rb +9 -0
  67. data/lib/aws-sdk-code-generator/views/types_module.rb +294 -0
  68. data/lib/aws-sdk-code-generator/views/version.rb +2 -0
  69. data/lib/aws-sdk-code-generator/views/waiters_module.rb +37 -0
  70. data/lib/aws-sdk-code-generator/waiter.rb +95 -0
  71. data/lib/aws-sdk-code-generator/yard_option_tag.rb +43 -0
  72. metadata +61 -68
  73. data/lib/aws-sdk-code-generator/dsl/access_control_statement.rb +0 -23
  74. data/lib/aws-sdk-code-generator/dsl/attribute_accessor.rb +0 -43
  75. data/lib/aws-sdk-code-generator/dsl/attribute_reader.rb +0 -11
  76. data/lib/aws-sdk-code-generator/dsl/attribute_writer.rb +0 -11
  77. data/lib/aws-sdk-code-generator/dsl/autoload_statement.rb +0 -15
  78. data/lib/aws-sdk-code-generator/dsl/block_param.rb +0 -11
  79. data/lib/aws-sdk-code-generator/dsl/class.rb +0 -27
  80. data/lib/aws-sdk-code-generator/dsl/code_literal.rb +0 -66
  81. data/lib/aws-sdk-code-generator/dsl/code_object.rb +0 -33
  82. data/lib/aws-sdk-code-generator/dsl/docstring.rb +0 -36
  83. data/lib/aws-sdk-code-generator/dsl/eigenclass.rb +0 -15
  84. data/lib/aws-sdk-code-generator/dsl/extend_statement.rb +0 -12
  85. data/lib/aws-sdk-code-generator/dsl/formatter.rb +0 -25
  86. data/lib/aws-sdk-code-generator/dsl/include_statement.rb +0 -17
  87. data/lib/aws-sdk-code-generator/dsl/main.rb +0 -105
  88. data/lib/aws-sdk-code-generator/dsl/method.rb +0 -108
  89. data/lib/aws-sdk-code-generator/dsl/module.rb +0 -167
  90. data/lib/aws-sdk-code-generator/dsl/option_tag.rb +0 -36
  91. data/lib/aws-sdk-code-generator/dsl/param.rb +0 -43
  92. data/lib/aws-sdk-code-generator/dsl/param_list.rb +0 -38
  93. data/lib/aws-sdk-code-generator/dsl/return_tag.rb +0 -19
  94. data/lib/aws-sdk-code-generator/dsl/tag_default.rb +0 -20
  95. data/lib/aws-sdk-code-generator/dsl/tag_docstring.rb +0 -27
  96. data/lib/aws-sdk-code-generator/dsl/tag_type.rb +0 -18
  97. data/lib/aws-sdk-code-generator/generators/client_api_module.rb +0 -334
  98. data/lib/aws-sdk-code-generator/generators/client_class.rb +0 -389
  99. data/lib/aws-sdk-code-generator/generators/client_operation_documentation.rb +0 -166
  100. data/lib/aws-sdk-code-generator/generators/errors_module.rb +0 -25
  101. data/lib/aws-sdk-code-generator/generators/resource/action.rb +0 -88
  102. data/lib/aws-sdk-code-generator/generators/resource/batch_builder.rb +0 -211
  103. data/lib/aws-sdk-code-generator/generators/resource/builder.rb +0 -50
  104. data/lib/aws-sdk-code-generator/generators/resource/client_getter.rb +0 -15
  105. data/lib/aws-sdk-code-generator/generators/resource/client_request.rb +0 -49
  106. data/lib/aws-sdk-code-generator/generators/resource/client_request_docs.rb +0 -97
  107. data/lib/aws-sdk-code-generator/generators/resource/client_request_params.rb +0 -88
  108. data/lib/aws-sdk-code-generator/generators/resource/collection_class.rb +0 -180
  109. data/lib/aws-sdk-code-generator/generators/resource/data_attribute_getter.rb +0 -24
  110. data/lib/aws-sdk-code-generator/generators/resource/data_loaded_method.rb +0 -18
  111. data/lib/aws-sdk-code-generator/generators/resource/data_method.rb +0 -49
  112. data/lib/aws-sdk-code-generator/generators/resource/exists_method.rb +0 -29
  113. data/lib/aws-sdk-code-generator/generators/resource/extract_identifier_method.rb +0 -32
  114. data/lib/aws-sdk-code-generator/generators/resource/has_association.rb +0 -101
  115. data/lib/aws-sdk-code-generator/generators/resource/has_many_association.rb +0 -108
  116. data/lib/aws-sdk-code-generator/generators/resource/identifier_getter.rb +0 -26
  117. data/lib/aws-sdk-code-generator/generators/resource/identifiers_method.rb +0 -28
  118. data/lib/aws-sdk-code-generator/generators/resource/initialize_method.rb +0 -67
  119. data/lib/aws-sdk-code-generator/generators/resource/load_method.rb +0 -65
  120. data/lib/aws-sdk-code-generator/generators/resource/value_source.rb +0 -68
  121. data/lib/aws-sdk-code-generator/generators/resource/waiter_method.rb +0 -61
  122. data/lib/aws-sdk-code-generator/generators/resource_class.rb +0 -325
  123. data/lib/aws-sdk-code-generator/generators/response_structure_example.rb +0 -83
  124. data/lib/aws-sdk-code-generator/generators/root_resource_class.rb +0 -42
  125. data/lib/aws-sdk-code-generator/generators/service_documentation.rb +0 -64
  126. data/lib/aws-sdk-code-generator/generators/shared_example.rb +0 -132
  127. data/lib/aws-sdk-code-generator/generators/structure_type_class.rb +0 -95
  128. data/lib/aws-sdk-code-generator/generators/syntax_example.rb +0 -169
  129. data/lib/aws-sdk-code-generator/generators/types_module.rb +0 -52
  130. data/lib/aws-sdk-code-generator/generators/waiter_class.rb +0 -62
  131. data/lib/aws-sdk-code-generator/generators/waiters_module.rb +0 -20
@@ -0,0 +1,212 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+
5
+ module AwsSdkCodeGenerator
6
+ class ResourceBatchBuilder
7
+
8
+ # @option options [required, Hash] :resource
9
+ # @option options [String] :resp_var_name ('resp')
10
+ def initialize(options)
11
+ @resource = options.fetch(:resource)
12
+ @resp_var_name = options.fetch(:resp_var_name, 'resp')
13
+ verify_resource!
14
+ @context = loop_context
15
+ @indent = options.fetch(:indent, '')
16
+ end
17
+
18
+ def build
19
+ code = ''
20
+ loops = self.send(:loops)
21
+ count = loops.size
22
+ loops.each.with_index do |loop_expression, n|
23
+ i = ' ' * n
24
+ code += "#{i}#{loop_expression}\n"
25
+ if n == count - 1
26
+ code += i + ' ' + Docstring.indent("batch << #{resource_class}.new(#{constructor_args})\n", i + ' ')
27
+ end
28
+ end
29
+ (count).times do |n|
30
+ i = ' ' * (count - n - 1)
31
+ code += "#{i}end\n"
32
+ end
33
+ code.rstrip
34
+ end
35
+
36
+ private
37
+
38
+ def resource_class
39
+ @resource['type']
40
+ end
41
+
42
+ def constructor_args
43
+ hash = {}
44
+ hash.update(identifiers)
45
+ hash[:data] = data_path if @resource['path']
46
+ hash[:client] = "@client"
47
+ HashFormatter.new(wrap:false, inline:true).format(hash)
48
+ end
49
+
50
+ def identifiers
51
+ (@resource['identifiers'] || []).inject({}) do |hash, identifier|
52
+ value = relative_identifier_path(identifier)
53
+ hash[underscore(identifier['target']).to_sym] = value
54
+ hash
55
+ end
56
+ end
57
+
58
+ def data_path
59
+ relative_identifier_path({
60
+ 'source' => 'data',
61
+ 'path' => @resource['path'],
62
+ })
63
+ end
64
+
65
+ def relative_identifier_path(identifier)
66
+ path = identifier['path']
67
+ if path && path.include?('[]')
68
+ prefix = loops.last.match(/\|(.+)\|/)[1]
69
+ suffix = underscore(path[common_prefix.length..-1])
70
+ unless @context == :response
71
+ suffix = suffix.gsub(/\.\w+/) { |word| "[:#{word[1..-1]}]" }
72
+ end
73
+ suffix.length == 0 ? prefix : prefix + suffix
74
+ else
75
+ ResourceValueSource.new(identifier).to_s
76
+ end
77
+ end
78
+
79
+ def common_prefix
80
+ paths = plural_paths
81
+ if paths.empty?
82
+ ''
83
+ elsif paths.size == 1
84
+ # grab everything upto and including the final []
85
+ paths.first.match(/(.+\[\]).*?$/)[1]
86
+ else
87
+ prefix = find_prefix(paths)
88
+ prefix = prefix.sub(/\[\].+?$/, '[]')
89
+ if prefix[-2..-1] != '[]'
90
+ msg = 'response paths must have a common prefix ending in [], got :'
91
+ msg << paths.inspect
92
+ raise ArgumentError, msg
93
+ else
94
+ prefix
95
+ end
96
+ end
97
+ end
98
+
99
+ def find_prefix(paths)
100
+ prefix = ''
101
+ loop.with_index do |_, n|
102
+ return prefix if paths.empty?
103
+ letter = paths[0][n]
104
+ paths.each do |path|
105
+ return prefix if path[n].nil?
106
+ return prefix if path[n] != letter
107
+ end
108
+ prefix += letter
109
+ end
110
+ end
111
+
112
+ def loops
113
+ loop_var =
114
+ case @context
115
+ when :data then 'data'
116
+ when :options then 'options'
117
+ when :response then "#{@resp_var_name}.data."
118
+ end
119
+
120
+ used_vars = Set.new
121
+ used_vars << loop_var
122
+
123
+ parts = common_prefix.split('[]')
124
+ parts = parts.map.with_index do |part,n|
125
+ part = underscore(part)
126
+ unless @context == :response
127
+ part = part.gsub(/\w+/) { |word| "[:#{word}]" }
128
+ part = part.gsub(/\./, '')
129
+ end
130
+ part = "#{loop_var}#{part}"
131
+ loop_var = loop_letter(part, used_vars)
132
+ part = part + ".each do |#{loop_var}|"
133
+ part
134
+ end
135
+ parts
136
+ end
137
+
138
+ def loop_letter(str, used_vars)
139
+ letter = if @context == :options
140
+ str.scan(/:\w/).last[1]
141
+ else
142
+ str.split('.').last[0]
143
+ end
144
+ n = 1
145
+ var = letter
146
+ while used_vars.include?(var)
147
+ n += 1
148
+ var = "#{letter}#{n}"
149
+ end
150
+ used_vars << var
151
+ var
152
+ end
153
+
154
+ def all_plural_paths
155
+ paths = {}
156
+ @resource['identifiers'].each do |i|
157
+ if i['path'] && i['path'].include?('[]')
158
+ paths[i['source']] ||= []
159
+ paths[i['source']] << i['path']
160
+ end
161
+ end
162
+ paths
163
+ end
164
+
165
+ def plural_paths
166
+ all_plural_paths.values.first
167
+ end
168
+
169
+ def verify_resource!
170
+ verify_plural_paths!
171
+ end
172
+
173
+ def verify_plural_paths!
174
+ paths = all_plural_paths
175
+ case paths.size
176
+ when 0
177
+ msg = 'expected at least one plural identifier path, got none'
178
+ raise ArgumentError, msg
179
+ when 1
180
+ case paths.keys.first
181
+ when 'requestParameter'
182
+ when 'response'
183
+ when 'data'
184
+ else
185
+ msg = "unsupported identifier source #{paths.keys.first.inspect}"
186
+ raise ArgumentError, msg
187
+ end
188
+ else
189
+ msg = 'mixing plural source types is not supported'
190
+ raise ArgumentError, msg
191
+ end
192
+ end
193
+
194
+ def loop_context
195
+ case all_plural_paths.keys
196
+ when ['response'] then :response
197
+ when ['data'] then :data
198
+ when ['requestParameter'] then :options
199
+ else
200
+ msg = "unable to determine loop context: #{@resource.inspect}"
201
+ raise msg
202
+ end
203
+ end
204
+
205
+ def underscore(str)
206
+ str.split('.').map do |part|
207
+ Underscore.underscore(part)
208
+ end.join('.')
209
+ end
210
+
211
+ end
212
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ class ResourceBuilder
5
+
6
+ # @option options [required, Hash] :resource
7
+ # @option options [required, Boolean] :request_made
8
+ def initialize(options = {})
9
+ @resource = options.fetch(:resource)
10
+ @request_made = options.fetch(:request_made)
11
+ end
12
+
13
+ def build
14
+ "#{resource_class}.new(#{constructor_options})"
15
+ end
16
+
17
+ private
18
+
19
+ def resource_class
20
+ @resource['type']
21
+ end
22
+
23
+ def constructor_options
24
+ options = {}
25
+ options.update(identifiers)
26
+ options[:data] = data_path if @resource['path']
27
+ options[:client] = "@client"
28
+ HashFormatter.new(wrap:false).format(options)
29
+ end
30
+
31
+ def identifiers
32
+ (@resource['identifiers'] || []).inject({}) do |hash, identifier|
33
+ value = ResourceValueSource.new(identifier).to_s
34
+ hash[Underscore.underscore(identifier['target']).to_sym] = value
35
+ hash
36
+ end
37
+ end
38
+
39
+ def data_path
40
+ if @request_made
41
+ ResourceValueSource.new('source' => 'response', 'path' => @resource['path'])
42
+ else
43
+ ResourceValueSource.new('source' => 'data', 'path' => @resource['path'])
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ class ResourceClientRequest
5
+ class << self
6
+
7
+ # @option options [required, Hash] :request
8
+ # @option options [Boolean] :resp (false)
9
+ # @option options [Boolean] :merge (true)
10
+ def build(options)
11
+ request = options.fetch(:request)
12
+ merge = options.fetch(:merge, true)
13
+ streaming = options.fetch(:streaming, false)
14
+ params = ResourceClientRequestParams.new(params: request['params'])
15
+ parts = []
16
+ parts << request_options(params) if merge
17
+ parts << assignment(options)
18
+ parts << "@client."
19
+ parts << operation_name(request)
20
+ parts << arguments(merge, params, streaming)
21
+ parts.join
22
+ end
23
+
24
+ private
25
+
26
+ def request_options(params)
27
+ if params.empty?
28
+ ''
29
+ elsif params.simple?
30
+ "options = options.merge(#{params})\n"
31
+ else
32
+ hash = params
33
+ hash = ' ' + hash unless hash[0] == "\n"
34
+ "options = Aws::Util.deep_merge(options,#{hash})\n"
35
+ end
36
+ end
37
+
38
+ def assignment(options)
39
+ if options.fetch(:resp, false)
40
+ 'resp = '
41
+ else
42
+ ''
43
+ end
44
+ end
45
+
46
+ def operation_name(request)
47
+ Underscore.underscore(request['operation'])
48
+ end
49
+
50
+ def arguments(merge, params, streaming)
51
+ if merge
52
+ streaming ? '(options, &block)' : '(options)'
53
+ elsif params.empty?
54
+ ''
55
+ else
56
+ streaming ? "(#{params}, &block)" : "(#{params})"
57
+ end
58
+ end
59
+
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'set'
4
+
5
+ module AwsSdkCodeGenerator
6
+ class ResourceClientReqeustDocumentation
7
+
8
+ def initialize(options)
9
+ @api = options.fetch(:api)
10
+ @method_name = options.fetch(:method_name)
11
+ @receiver = options.fetch(:receiver)
12
+ @resp_var = options.fetch(:resp_var, nil)
13
+ @request = options.fetch(:request)
14
+ @shape_ref = @api['operations'][@request['operation']]['input']
15
+ @returns = options.fetch(:returns, nil)
16
+ @skip = Set.new(options.fetch(:skip, []) + ResourceSkipParams.compute(input_shape, @request))
17
+ end
18
+
19
+ def build
20
+ Docstring.join_docstrings([
21
+ request_syntax_example,
22
+ param_tag,
23
+ option_tags,
24
+ return_tag,
25
+ ], block_comment: false, separator: false)
26
+ end
27
+
28
+ private
29
+
30
+ def request_syntax_example
31
+ if @shape_ref && Api.shape(@shape_ref, @api)['members'].count - @skip.count > 0
32
+ SyntaxExample.new(
33
+ api: @api,
34
+ shape: input_shape,
35
+ method_name: @method_name,
36
+ receiver: @receiver,
37
+ resp_var: @resp_var,
38
+ skip: @skip,
39
+ ).format
40
+ else
41
+ # TODO : remove these empty examples, not really needed
42
+ <<-DOCS.rstrip
43
+ # @example Request syntax with placeholder values
44
+ #
45
+ # #{@receiver}.#{@method_name}()
46
+ DOCS
47
+ end
48
+ end
49
+
50
+ def param_tag
51
+ '# @param [Hash] options ({})'
52
+ end
53
+
54
+ def option_tags
55
+ if input_shape
56
+ input_shape['members'].map do |member_name, member_ref|
57
+ next if @skip.include?(member_name)
58
+ YardOptionTag.new(
59
+ name: Underscore.underscore(member_name),
60
+ required: input_shape.fetch('required', []).include?(member_name),
61
+ ruby_type: Api.ruby_input_type(member_ref, @api),
62
+ docstring: Docstring.html_to_markdown(Api.docstring(member_ref, @api)),
63
+ ).to_str
64
+ end
65
+ end
66
+ end
67
+
68
+ def input_shape
69
+ Api.shape(@shape_ref, @api)
70
+ end
71
+
72
+ def return_tag
73
+ if @returns
74
+ "# @return [#{@returns}]"
75
+ else
76
+ nil
77
+ end
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AwsSdkCodeGenerator
4
+ class ResourceClientRequestParams < String
5
+
6
+ include Helper
7
+
8
+ # @option options [Array] :params ([])
9
+ def initialize(options = {})
10
+ @params = options.fetch(:params, nil) || []
11
+ super(format_params)
12
+ end
13
+
14
+ def simple?
15
+ @params.all? { |p| p['target'].match(/^\w+$/) }
16
+ end
17
+
18
+ def empty?
19
+ @params.empty?
20
+ end
21
+
22
+ def size
23
+ @params.size
24
+ end
25
+
26
+ private
27
+
28
+ def format_params
29
+ hash = {}
30
+ @params.each do |param|
31
+ ParamTarget.new(param).apply(hash, ResourceValueSource.new(param))
32
+ end
33
+ formatter = HashFormatter.new(wrap:false, inline: @params.count == 1)
34
+ params = formatter.format(hash)
35
+ @params.size == 1 ? params.strip : params
36
+ end
37
+
38
+ class ParamTarget
39
+
40
+ def initialize(param)
41
+ @target = param['target']
42
+ @steps = []
43
+ @target.scan(/\w+|\[\]|\[\*\]|\[[0-9]+\]/) do |step|
44
+ case step
45
+ when /\[\d+\]/ then @steps += [:array, step[1..-2].to_i]
46
+ when /\[\*\]/ then @steps += [:array, :n]
47
+ when '[]' then @steps += [:array, -1]
48
+ else @steps += [:hash, Underscore.underscore(step).to_sym]
49
+ end
50
+ end
51
+ @steps.shift
52
+ @final = @steps.pop
53
+ end
54
+
55
+ # @return [String] target
56
+ attr_reader :target
57
+
58
+ def apply(hash, value, options = {})
59
+ resource_index = options.fetch(:resource_index, 0)
60
+ if @final == -1
61
+ build_context(hash, resource_index) << value
62
+ else
63
+ build_context(hash, resource_index)[@final] = value
64
+ end
65
+ hash
66
+ end
67
+
68
+ private
69
+
70
+ def build_context(params, n)
71
+ @steps.each_slice(2).inject(params) do |context, (key, type)|
72
+ entry = type == :array ? [] : {}
73
+ if key == -1
74
+ context << entry
75
+ entry
76
+ elsif key == :n
77
+ context[n] ||= entry
78
+ else
79
+ context[key] ||= entry
80
+ end
81
+ end
82
+ end
83
+
84
+ end
85
+ end
86
+ end