tla-sbuilder 0.2.2 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +150 -116
  3. data/VERSION +1 -1
  4. data/lib/cli/cli-customer.rb +23 -3
  5. data/lib/cli/cli-pet.rb +66 -12
  6. data/lib/cli/cli-text.rb +127 -8
  7. data/lib/cli/cli.rb +49 -6
  8. data/lib/sbuilder.rb +26 -3
  9. data/lib/sbuilder/constants.rb +165 -6
  10. data/lib/sbuilder/controller.rb +943 -169
  11. data/lib/sbuilder/controller_utils.rb +122 -0
  12. data/lib/sbuilder/default-sbuilder.yaml +38 -44
  13. data/lib/sbuilder/domain.rb +160 -36
  14. data/lib/sbuilder/domain_cardinality.rb +1 -1
  15. data/lib/sbuilder/domain_range.rb +102 -0
  16. data/lib/sbuilder/domain_type.rb +150 -0
  17. data/lib/sbuilder/domain_value.rb +21 -13
  18. data/lib/sbuilder/exception.rb +16 -0
  19. data/lib/sbuilder/extension_loader.rb +67 -686
  20. data/lib/sbuilder/extension_loader_deprecated_step_extensions.rb +711 -0
  21. data/lib/sbuilder/extension_loader_step_generator.rb +876 -0
  22. data/lib/sbuilder/facade/{api_loader.rb → api_loader_facade.rb} +176 -45
  23. data/lib/sbuilder/facade/api_loader_plugin.rb +6 -32
  24. data/lib/sbuilder/facade/api_loader_plugin_mixer.rb +35 -0
  25. data/lib/sbuilder/facade/facade_constants.rb +23 -0
  26. data/lib/sbuilder/facade/loader_plugin_root.rb +56 -0
  27. data/lib/sbuilder/facade/param_set_root.rb +55 -0
  28. data/lib/sbuilder/facade/snippet_loader_facade.rb +600 -0
  29. data/lib/sbuilder/facade/snippet_loader_plugin.rb +76 -0
  30. data/lib/sbuilder/facade/snippet_loader_plugin_mixer.rb +56 -0
  31. data/lib/sbuilder/factory.rb +224 -45
  32. data/lib/sbuilder/model.rb +125 -45
  33. data/lib/sbuilder/mustache/template.rb +107 -58
  34. data/lib/sbuilder/mustache/template_reader.rb +56 -46
  35. data/lib/sbuilder/mustache/template_reader_context.rb +64 -234
  36. data/lib/sbuilder/mustache/template_resolve.rb +103 -0
  37. data/lib/sbuilder/mustache/template_root.rb +71 -0
  38. data/lib/sbuilder/param_set.rb +30 -15
  39. data/lib/sbuilder/param_set_db.rb +1 -1
  40. data/lib/sbuilder/param_set_def.rb +6 -1
  41. data/lib/sbuilder/param_set_def_func.rb +39 -0
  42. data/lib/sbuilder/param_set_if.rb +45 -10
  43. data/lib/sbuilder/param_set_loader_swagger.rb +56 -26
  44. data/lib/sbuilder/param_set_step.rb +1 -1
  45. data/lib/sbuilder/param_sets.rb +2 -1
  46. data/lib/sbuilder/parameter.rb +9 -3
  47. data/lib/sbuilder/parameter_container.rb +1 -1
  48. data/lib/sbuilder/parameter_dom.rb +17 -5
  49. data/lib/sbuilder/parameter_ref.rb +39 -10
  50. data/lib/sbuilder/parser/parser_facade.rb +310 -0
  51. data/lib/sbuilder/resolver.rb +11 -6
  52. data/lib/sbuilder/resolver_loader.rb +1 -1
  53. data/lib/sbuilder/resolver_loader_yaml.rb +1 -1
  54. data/lib/sbuilder/resolver_rule.rb +1 -1
  55. data/lib/sbuilder/resolver_rule_match.rb +10 -4
  56. data/lib/sbuilder/resolver_rule_ref.rb +1 -1
  57. data/lib/sbuilder/setup_loader.rb +49 -0
  58. data/lib/sbuilder/setup_loader_env.rb +478 -0
  59. data/lib/sbuilder/setup_loader_pref.rb +56 -0
  60. data/lib/sbuilder/snippet_loader_simple.rb +125 -0
  61. data/lib/sbuilder/spec/api_loader.rb +34 -0
  62. data/lib/sbuilder/spec/api_loader_facade.rb +169 -32
  63. data/lib/sbuilder/spec/loader_plugin.rb +98 -0
  64. data/lib/sbuilder/spec/snippet_loader.rb +228 -0
  65. data/lib/sbuilder/symbol_table.rb +279 -0
  66. data/lib/utils/{cache_lines.rb → fileio.rb} +8 -1
  67. data/lib/utils/logger.rb +2 -1
  68. data/lib/utils/powerset.rb +13 -0
  69. data/lib/utils/validate.rb +38 -0
  70. data/mustache/cfg/const_def.mustache +2 -0
  71. data/mustache/cfg/macro_run.mustache +1 -4
  72. data/mustache/data-model-header.mustache +1 -0
  73. data/mustache/definition_types.mustache +34 -4
  74. data/mustache/domains.mustache +1 -1
  75. data/mustache/domains_assign.mustache +1 -1
  76. data/mustache/infrastructure-service-init.mustache +1 -1
  77. data/mustache/interface_processes.mustache +16 -10
  78. data/mustache/interface_types.mustache +37 -11
  79. data/mustache/operator-infrastructure-service.mustache +1 -1
  80. data/mustache/resources/schedule_operator_new_step.tla +8 -0
  81. data/mustache/resources/schedule_process_macro.tla +37 -0
  82. data/mustache/resources/schedule_process_procedure.tla +22 -0
  83. data/mustache/resources/schedule_throw.tla +16 -0
  84. data/mustache/setup/domains_run.mustache +8 -2
  85. data/mustache/setup/operator_run.mustache +0 -4
  86. data/mustache/setup/steps_run.mustache +4 -3
  87. data/mustache/setup/steps_run_parameterBind.mustache +14 -6
  88. data/mustache/setup/steps_run_parameterExact.mustache +7 -3
  89. data/mustache/state_type_invariant-infrastructure-service.mustache +9 -4
  90. data/mustache/tla/const_def.mustache +1 -1
  91. data/mustache/tla/macro_run.mustache +7 -1
  92. data/mustache/tla/module_header.mustache +1 -1
  93. data/mustache/tla/operator_run.mustache +8 -5
  94. data/mustache/tla/plc_define_run.mustache +45 -36
  95. data/mustache/tla/plc_run_state.mustache +12 -5
  96. data/src-extend/extend/extend_assumptions.mustache +3 -0
  97. data/src-extend/extend/extend_const.mustache +3 -0
  98. data/src-extend/extend/extend_implementation.mustache +3 -0
  99. data/src-extend/extend/extend_invariant.mustache +3 -0
  100. data/src-extend/extend/extend_macros.mustache +3 -0
  101. data/src-extend/extend/extend_operations.mustache +3 -0
  102. data/src-extend/extend/extend_state.mustache +3 -0
  103. data/src/pet/extend/extend_assumptions.mustache +4 -0
  104. data/src/pet/extend/extend_implementation.mustache +3 -0
  105. data/src/pet/extend/extend_invariant.mustache +3 -0
  106. data/src/pet/extend/extend_macros.mustache +3 -0
  107. data/src/pet/extend/extend_operations.mustache +4 -0
  108. data/src/pet/extend/extend_state.mustache +3 -0
  109. data/src/pet/interface +5 -5
  110. data/src/pet/interface_delete_pet.tla +1 -1
  111. data/src/pet/interface_get_pet.tla +1 -1
  112. data/src/pet/interface_post_pet.tla +4 -2
  113. data/src/pet/interface_post_tag.tla +1 -1
  114. data/src/pet/interface_put_tag.tla +1 -1
  115. data/tla-sbuilder.gemspec +3 -3
  116. metadata +44 -19
  117. data/mustache/name_definition_type.mustache +0 -5
  118. data/mustache/name_domain.mustache +0 -5
  119. data/mustache/name_domain_value.mustache +0 -5
  120. data/mustache/name_domain_value_prefix.mustache +0 -5
  121. data/mustache/name_interface_response_type.mustache +0 -6
  122. data/mustache/name_interface_type.mustache +0 -6
  123. data/mustache/name_parameter_type.mustache +0 -6
  124. data/mustache/name_process.mustache +0 -6
  125. data/mustache/state_type_invariant.mustache +0 -17
  126. data/mustache/state_variables.mustache +0 -20
  127. data/src-extend/extend/extend_invariant_cfg.mustache +0 -7
@@ -0,0 +1,876 @@
1
+ # coding: utf-8
2
+ module Sbuilder
3
+ #
4
+ # This module is used to generate paramter bindings for interface operations
5
+ #
6
+ # API usage:
7
+ #
8
+ # step_generator = Sbuilder::StepGenerator.new
9
+ #
10
+ # step_generator.initParamSet( inputParamSet, validators )
11
+ # values = step_generator.values
12
+ # if values.nil?
13
+ # puts "no value"
14
+ # else
15
+ # values.each do {|value| puts value }
16
+ # end
17
+ #
18
+ # Data model:
19
+ #
20
+ #
21
+ # +----------------+
22
+ # | |<-----------------+
23
+ # | Parameter set | |
24
+ # | | |
25
+ # +----------------+ |
26
+ # | |
27
+ # | |
28
+ # +-------*--------+ |
29
+ # | | |
30
+ # | Parameter | |
31
+ # | | |
32
+ # +----------------+ |
33
+ # A |
34
+ # | |
35
+ # +------------+---------------+ |
36
+ # | | |
37
+ # | | |
38
+ # +----------------+ +----------------+ |
39
+ # | | | | |
40
+ # | Domain paramate| | Ref. parameter |---+
41
+ # | | | |
42
+ # +----------------+ +----------------+
43
+ # |
44
+ # |
45
+ # +----------------+
46
+ # | |
47
+ # | Domain |
48
+ # | |
49
+ # +----------------+
50
+ #
51
+ #
52
+ # - A parameter set is a composition of parameters.
53
+ # - A parameter is domain parmeter or reference paramter.
54
+ # - Domain parmater reference domain (definin values for parameter)
55
+ # - Reference paramter refers to paramater set
56
+ # - A parameter definies 'name' property
57
+ # - A parameter definies 'isArray' property
58
+ #
59
+ #
60
+ # Generating values (nextValue operation)
61
+ #
62
+ # - domain parameter: Cycle a pointer trough values in parameter
63
+ # domain. Return false, when pointer cycles from last domain entry
64
+ # to the first domain entry, else return true.
65
+
66
+ # - parameter set: iterate all parameters in the parameter set,
67
+ # return 'true', when first parameter nextValue returns 'true',
68
+ # return false if none of parameter nextValue operations return
69
+ # 'true'.
70
+ #
71
+ # - array parameter (for domain parameter and refernce parameter):
72
+ # parameter domain is powerset of the underlying value range.
73
+ #
74
+ # - exceptions raised
75
+ # -- when creating powerset for set with cardilality >= 6
76
+ # -- when cardinality of reference set exceeds >= 100
77
+ #
78
+ # Input:
79
+ #
80
+ # 'validators' is an array of "rule", "rule_value", "action",
81
+ # "action_value" -properties. Property "rule" checks, whether "action"
82
+ # prorperty should be used screen domain values, when genarating
83
+ # value binding to paramters.
84
+ #
85
+ # Valid values for "rule" property are defined in RULES array. In
86
+ # this array, "rule" property is mapped to a lambda function
87
+ # returning boolean value. First "action", where "rule" lambda return
88
+ # true is applied, an error is raised if no valid "rule" is
89
+ # found. Optional property "rule_value" is passed to the lamdba
90
+ # function, along with parameter object, and the the path to the
91
+ # paramter in parameter set.
92
+ #
93
+ # Valid values for "action" property are defined in ACTIONS
94
+ # array. This array maps "action" property value to lambda function
95
+ # returning boolean, if given domain value should be used in value
96
+ # binding. Property "action_value" is passed to the lambda function,
97
+ # along with domain index, and domain value to check.
98
+ #
99
+ #
100
+
101
+ #
102
+
103
+ # module implementing '@validIndex' and '@validValues' array to
104
+ # return values.
105
+ #
106
+ # Class including this module must implement 'validValuesSet'
107
+
108
+ module StepGeneratorValue
109
+
110
+
111
+ # @attr [Integer] index array valid values
112
+ attr_accessor :validIndex
113
+
114
+ # ------------------------------------------------------------------
115
+ # @!group Public services
116
+
117
+ # Update 'memo' key 'parameterName' with current 'validValue'
118
+ #
119
+ # @param [Hash] memo hash where current 'validValue' gets updated
120
+ #
121
+ # @return [Boolean,Hash] true when valid value found, updated 'memo'
122
+ def currentValue( memo )
123
+ currentValue = validValue( validIndex )
124
+ memo[parameterName] = currentValue
125
+ return !currentValue.nil?, memo
126
+ end
127
+
128
+ # Advance '@validIndex' to point to next valid entry in
129
+ # '@validValue' -set.
130
+ #
131
+ # @return [Boolean] true is not wrapped around
132
+ def nextValue
133
+
134
+ self.validIndex= validIndex + 1
135
+
136
+ # loop until next valid value found (or wrapped around)
137
+ if validIndex >= validValueCount
138
+ # Wrapped around
139
+ self.validIndex= 0
140
+ return false
141
+ end
142
+
143
+ # not wrapped around
144
+ return true
145
+
146
+ end
147
+
148
+ # @!endgroup
149
+
150
+ # ------------------------------------------------------------------
151
+ # @!group Implement set of valid values
152
+
153
+ # @return [String] element in position 'indx' of 'validValues'
154
+ def validValue( indx )
155
+ validValues[indx]
156
+ end
157
+
158
+
159
+ # @return [Integer] number of domain elements passed 'action'
160
+ # validation
161
+ def validValueCount
162
+ validValues.length
163
+ end
164
+
165
+ # Return (cached ) set of valid values. For non isArray generator
166
+ # return 'validValuesSet', else (i.e. isArray = true ) return
167
+ # powerset( validValuesSet )
168
+ #
169
+ # @return [String:Array|Hash:Array] valid_values set for parameter
170
+ #
171
+ def validValues
172
+ return @validValues if @validValues
173
+
174
+ Sbuilder::StepGenerator.logger.info "#{__method__}, parameter=#{parameter.name}, isArray=#{isArray}, validValuesSet.length=#{validValuesSet.length}"
175
+
176
+ Sbuilder::StepGenerator.maxPowerSet( validValuesSet.length ) if isArray
177
+ @validValues = isArray ? Sbuilder::Powerset.powerset( validValuesSet ) : validValuesSet
178
+
179
+ return @validValues
180
+ end
181
+
182
+ # @!endgroup
183
+
184
+
185
+ end # module StepGeneratorValue
186
+
187
+ # ------------------------------------------------------------------
188
+
189
+
190
+ class StepGenerator
191
+
192
+ PROGNAME = nil # progname for logger default class name
193
+ include Sbuilder::Utils::MyLogger # mix logger
194
+
195
+
196
+ # check validator hash properties
197
+ @@validator_required = %w( rule action )
198
+ @@validator_allowed = %w( action_value rule_value )
199
+
200
+ # @attr [Sbuilder::ParamSet] paramSet initilized to generates values
201
+ attr_accessor :paramSet
202
+
203
+ # @attr [StepGeneratorValueDomain:Array] generating value
204
+ attr_reader :domainValues
205
+
206
+ RULES = {
207
+ # triggers on all fields
208
+ 'default' => -> (parameter, path, rule_value) { true },
209
+ # triiggers on field with 'path' matching 'rule_value'
210
+ 'path' => -> (parameter, path, rule_value ) { path == rule_value },
211
+ }
212
+
213
+ ACTIONS = {
214
+ # all domain values are used in value binding, does not yield
215
+ # fixed value
216
+ 'all' => {
217
+ :func => -> (index,domValue,validator_value) { true },
218
+ :fixedValue => false,
219
+ },
220
+ # no domain values are used in value binding, fixed value (no values)
221
+ 'none' => {
222
+ :func => -> (index,domValue,validator_value) { false },
223
+ :fixedValue => true,
224
+ },
225
+ # only domain value in "action_value" is used in value binding,
226
+ # fixed value (one domain element)
227
+ 'domain' => {
228
+ :func => -> (index,domValue,validator_value) { index==validator_value },
229
+ :fixedValue => true,
230
+ },
231
+ }
232
+
233
+ # known rules have an entry here
234
+ #
235
+ # @options RULE_VALIDATION [Array] :required array of properties
236
+ # required in validator
237
+ #
238
+ # @options RULE_VALIDATION [Array] :allowed array of properties
239
+ # allowed in validator
240
+ #
241
+ # @options RULE_VALIDATION [Array] :advance lambda function to act
242
+ # on 'validator' when recurding down paramter sets
243
+ RULE_VALIDATION = {
244
+ 'path' =>{
245
+ :required => %w( rule_value ),
246
+ :allowed => [],
247
+ },
248
+ 'default' =>{
249
+ :required => [],
250
+ :allowed => [],
251
+ }
252
+ }
253
+
254
+ # known actions have an entry here
255
+ ACTION_VALIDATION = {
256
+ 'domain' =>{
257
+ :required => %w( action_value ),
258
+ :allowed => []
259
+ },
260
+ 'all' =>{
261
+ :required => [],
262
+ :allowed => [],
263
+ },
264
+ 'none' =>{
265
+ :required => [],
266
+ :allowed => [],
267
+ }
268
+ }
269
+
270
+
271
+
272
+ # ------------------------------------------------------------------
273
+ # @!group Constructor & build
274
+
275
+ def initialize( options = {} )
276
+ if !defined?(@@logger )
277
+ @@logger =getLogger( PROGNAME, options )
278
+ end
279
+ @@logger.info( "#{__method__} initialized, options=#{options}" )
280
+ end
281
+
282
+ # Allow the one logger to be accessed via class method (within module)
283
+ def self.logger
284
+ @@logger
285
+ end
286
+
287
+ def isArray
288
+ paramSet.respond_to?( :isArray ) && paramSet.isArray
289
+
290
+ end
291
+
292
+ # Public service to associate step generator with parameter set,
293
+ # activate validator lamdb for each parameter in parameter set.
294
+ #
295
+ # @param [Sbuilder::ParamSet] initSet used to generate values
296
+ def initParamSet( initSet, validators=[ {"rule"=>'default', "action"=>'none'} ], parameter_path=[] )
297
+ # validator congiruation ok wrt initSet
298
+ validateValidators( initSet, validators )
299
+
300
+ # no path yet
301
+ parameter_path = []
302
+ startGenerator( initSet, validators, parameter_path )
303
+
304
+ end
305
+
306
+ # Module internal service, which actually implemented 'initParamSet'
307
+ def startGenerator( initSet, validators, parameter_path )
308
+
309
+ Sbuilder::StepGenerator.logger.info "#{__method__}, parameter.length = #{initSet.parameters.length}, validators=#{validators.join(',')}"
310
+
311
+ self.paramSet= initSet
312
+
313
+ @domainValues = []
314
+ paramSet.parameters.each do |parameter|
315
+
316
+ case [parameter.class]
317
+ when [Sbuilder::Parameter_Dom]
318
+ validator, action_value, fixedValue = chooseValidator( parameter, validators, parameter_path )
319
+ domainValue = StepGeneratorValueDomain.new( parameter, validator, action_value, parameter_path, fixedValue )
320
+ @domainValues << domainValue
321
+ when [Sbuilder::Parameter_Ref]
322
+ referenceValue = StepGeneratorValueRef.new( parameter, validators, parameter_path )
323
+ @domainValues << referenceValue
324
+ else
325
+ msg = "Unknown class #{parameter.class}"
326
+ Sbuilder::StepGenerator.logger.error msg
327
+ raise msg
328
+ end # case
329
+ end # each
330
+
331
+ # # if somethig generated
332
+ # val = currentValue
333
+
334
+ # # return empty array else nil
335
+ # return val.nil? ? val : [ ]
336
+
337
+ end
338
+
339
+
340
+ # Iterate 'validators' and activate validator["action"] for first
341
+ # 'validator["rule"]' matching for 'parameter'
342
+ #
343
+ # @param [Sbuilder::Parameter] parameter for which validator should be returned
344
+ #
345
+ # @param [Hash:Array] validator array of rules choosing validator
346
+ #
347
+ # @option validator [lambda] "rule" to match with 'parameter'
348
+ #
349
+ # @option validator [lambda] "action" to validate domains values in
350
+ # 'parameter' 'domain'
351
+ #
352
+ # @return [Lambda, String, Boolean] actionLambda, action_value,
353
+ # fixedValue
354
+ private def chooseValidator( parameter, validators, parameter_path )
355
+
356
+ validators = validators || []
357
+
358
+ validators.each do |validator|
359
+ if RULES[validator["rule"]].call( parameter, parameter_path + [parameter.name], validator["rule_value"] )
360
+ # returns two! values
361
+ return instantiateValidator( parameter, validator["action"] ), validator["action_value"], ACTIONS[validator["action"]][:fixedValue]
362
+ end
363
+ end # each validators
364
+ msg = <<-EOS
365
+ Could not locate validator for parameter #{parameter}
366
+
367
+ No matching rule found in validators: [ #{validators.join(',')} ]
368
+ EOS
369
+ Sbuilder::StepGenerator.logger.error msg
370
+ raise StepGeneratorException.new, msg
371
+ end
372
+
373
+ private def instantiateValidator( parameter, validatorAction )
374
+ if ACTIONS[validatorAction].nil?
375
+ msg = <<-EOS
376
+ Unknown validator action '#{validatorAction}' when instantiating validator for parameter #{parameter}.
377
+
378
+ Valid validator action names: #{ACTIONS.keys.join(',')}
379
+ EOS
380
+ Sbuilder::StepGenerator.logger.error msg
381
+ raise StepGeneratorException.new, msg
382
+ end
383
+ ACTIONS[validatorAction][:func]
384
+ end
385
+
386
+ # @!endgroup
387
+
388
+ # ------------------------------------------------------------------
389
+ # @!group Build values set
390
+
391
+ # Iterate all parmeters and return with 'true' for the first
392
+ # parameter, which can be advanced. If none of the parameter can
393
+ # be advances, return false. Advancing a parameter cycles a
394
+ # pointer to the next value in an array for valid value bindings
395
+ # for the paramter.
396
+ #
397
+ # @return [Boolean] true is next value generated, false when no more values to return
398
+ def nextValue()
399
+ goon = false
400
+ domainValues.each do |domainValue|
401
+ goon = goon || domainValue.nextValue
402
+ break if goon
403
+ end
404
+ goon
405
+ end
406
+
407
+ # Retrieve current value (stepped)
408
+ #
409
+ # @return [Hash] current value if valid value found, nil if no current value found
410
+ def currentValue
411
+ memo={}
412
+ # toggle true - if at least one memo element gets generated
413
+ anyValueFound = false
414
+ domainValues.each do |domainValue|
415
+ valueFound,memo = domainValue.currentValue( memo )
416
+ anyValueFound = anyValueFound || valueFound
417
+ end
418
+ # # if value found
419
+ # anyValueFound ? memo : nil
420
+ memo
421
+
422
+ end
423
+
424
+ # @!endgroup
425
+
426
+ # ------------------------------------------------------------------
427
+ # @!group Implement set of valid values
428
+
429
+ # @return [nil|Values] return (cached) value set generated by this generated
430
+ def values
431
+
432
+ Sbuilder::StepGenerator.logger.info "#{__method__}, @values=#{@values}, lengh=#{ @values.is_a?(Array) ? @values.length : 'undefined' }"
433
+
434
+ return @values if @values
435
+
436
+ # ensure that we do not return sets too large
437
+ Sbuilder::StepGenerator.maxSet( validValuesSetCardinality, nil )
438
+
439
+ baseSet = doValues
440
+
441
+ Sbuilder::StepGenerator.logger.info "#{__method__}, isArray=#{isArray}, baseSet.length=#{baseSet.length}, validValuesSetCardinality=#{validValuesSetCardinality}"
442
+
443
+ # ensure that powerset does not grow too large
444
+ Sbuilder::StepGenerator.maxPowerSet( baseSet.length ) if isArray
445
+ @values = isArray ? Sbuilder::Powerset.powerset( baseSet ) : baseSet
446
+
447
+ return @values
448
+ end
449
+
450
+ def doValues
451
+ val = currentValue
452
+ return nil unless val
453
+ vals = [val]
454
+ while nextValue
455
+ vals << currentValue
456
+ end
457
+ vals
458
+ end
459
+
460
+ # @!endgroup
461
+
462
+ # ------------------------------------------------------------------
463
+ # @!group Implement set of valid values
464
+
465
+ # @param [Integer] size of set used to generate powerset
466
+ #
467
+ # @return [Integer] max elements in set used to generate powerset
468
+ def self.maxPowerSet( size )
469
+ self.maxSet( 2 ** size, nil )
470
+ end
471
+
472
+ # @param [Integer] cardinality number of elemets in a set
473
+ #
474
+ # @param [Sbuilder:Parameter] parameter where cardinality violated
475
+ #
476
+ # @param [Integer] maxElements number of elements to check
477
+ # againts, normally use default value,
478
+ #
479
+ #
480
+ #
481
+ def self.maxSet( cardinality, parameter, maxElements=32)
482
+ if ( cardinality > maxElements )
483
+ msg = <<-EOS
484
+ Set cardinality '#{cardinality}' too large, max allowed( #{maxElements}).
485
+
486
+ EOS
487
+ msg += <<-EOS if parameter
488
+
489
+ when considering domains for parameter '#{parameter.name}'
490
+ EOS
491
+
492
+ Sbuilder::StepGenerator.logger.error msg
493
+ raise StepGeneratorException.new, msg
494
+ end
495
+ end
496
+
497
+ # Multiply cardinalities of referenced parameters for the
498
+ # cardinality of generator (base set i.e. WITHOUT considering
499
+ # isArray property in @paramSet).
500
+ #
501
+ # @return [Integer] cardinality of the generated set
502
+ def validValuesSetCardinality
503
+
504
+ totalCardinality = 1
505
+ domainValues.each do |domainValue|
506
+ totalCardinality *= domainValue.validValuesSetCardinality
507
+ end
508
+ Sbuilder::StepGenerator.logger.info "#{__method__}, totalCardinality=#{totalCardinality}"
509
+ totalCardinality
510
+
511
+ end
512
+
513
+ # Validate that validators are correct w.r.t. initSet. Check for
514
+ # mandatory properties, valid 'rule', and 'action' properities,
515
+ # valid properties for 'rule' and 'action'.
516
+ #
517
+ # @param [Sbuilder::ParamSet] initSet used to generate values
518
+ #
519
+ #
520
+ # @param [Hash:Array] validators
521
+ # @option validator [] rule
522
+ # @option validator [] rule_value
523
+ # @option validator [] action
524
+ # @option validator [] action_value
525
+
526
+ # "action_value" -properties.
527
+ def validateValidators( initSet, validators )
528
+
529
+ validators.each do |validator|
530
+
531
+ # mantatory properties
532
+ Sbuilder::Utils::Validate.validateProperties( validator, @@validator_required, @@validator_allowed )
533
+
534
+ # known rule
535
+ if RULES[validator["rule"]].nil?
536
+ msg= <<-EOS
537
+ Unknown validator rule '#{validator["rule"]}'
538
+
539
+ Valid validator rules: #{RULES.keys.join(',')}
540
+
541
+ EOS
542
+ Sbuilder::StepGenerator.logger.error msg
543
+ raise StepGeneratorException.new, msg
544
+
545
+ end
546
+
547
+ # known actions
548
+ if ACTIONS[validator["action"]].nil?
549
+ msg= <<-EOS
550
+ Unknown validator action '#{validator["action"]}'
551
+
552
+ Valid validator rules: #{ACTIONS.keys.join(',')}
553
+
554
+ EOS
555
+ Sbuilder::StepGenerator.logger.error msg
556
+ raise StepGeneratorException.new, msg
557
+
558
+ end
559
+
560
+ # rule configuration ok?
561
+ Sbuilder::Utils::Validate.validateProperties(
562
+ validator,
563
+ RULE_VALIDATION[validator['rule']][:required],
564
+ @@validator_required + @@validator_allowed + RULE_VALIDATION[validator['rule']][:allowed] )
565
+
566
+ # action validation configuration ok?
567
+ Sbuilder::Utils::Validate.validateProperties(
568
+ validator,
569
+ ACTION_VALIDATION[validator['action']][:required],
570
+ @@validator_required + @@validator_allowed + ACTION_VALIDATION[validator['action']][:allowed] )
571
+
572
+ if validator['rule'] == 'path'
573
+ validatePath( initSet, validator['rule_value'] )
574
+ end
575
+
576
+ end
577
+ end
578
+
579
+ # @param [Sbuilder::ParamSet] paramSet where path should be exist
580
+ #
581
+ # @param [String:Array] array of parameter names
582
+ def validatePath( initSet, path )
583
+
584
+ # init loop
585
+ currentSet = initSet
586
+
587
+ # each path element must find define a path in the tree defined
588
+ # by parameter set
589
+ path.each do |parameterName|
590
+ parameter = currentSet.lookupParameter( parameterName )
591
+ if parameter.nil?
592
+ msg= <<-EOS.unindent
593
+ Path element '#{parameterName}' does not match any valid parameter name: #{currentSet.parameters.map{|p|p.name}.join(',')}
594
+
595
+ Error occurred when trying to resolve path #{path} starting from parameter set
596
+ with parameter names: #{initSet.parameters.map{|p|p.name}.join(',')}
597
+ EOS
598
+ Sbuilder::StepGenerator.logger.error msg
599
+ raise StepGeneratorException.new, msg
600
+ end
601
+ # advance to next if possible
602
+ currentSet = parameter.respond_to?( :getResolvedReference ) ? parameter.getResolvedReference : nil
603
+ end
604
+ end
605
+
606
+ # @!endgroup
607
+
608
+
609
+ end
610
+
611
+
612
+
613
+ # ------------------------------------------------------------------
614
+
615
+ # Abstact class for generating values
616
+ class StepGeneratorValueRoot
617
+
618
+ # ədd '@validIndex' and @validValues, must implement
619
+ # validValuesSet and validValuesSetCardinality
620
+ include Sbuilder::StepGeneratorValue
621
+
622
+ # @attr [Sbuilder::Parameter_Dom|Sbuilder::Parameter_Ref] parameter generating value
623
+ attr_accessor :parameter
624
+
625
+ # @attr [String:Array] path to parent
626
+ attr_accessor :parameter_path
627
+
628
+
629
+ # ------------------------------------------------------------------
630
+ # @!group Construct & configure
631
+
632
+ def initialize( parameter, parameter_path )
633
+ self.parameter= parameter
634
+ self.parameter_path = parameter_path
635
+ self.validIndex = 0
636
+ Sbuilder::StepGenerator.logger.debug "#{__method__}, parameter=#{parameter.name}, isArray=#{isArray}"
637
+ end
638
+
639
+ # @return name of parameter generating values
640
+ def parameterName
641
+ parameter.name
642
+ end
643
+
644
+ # @return [Boolean] true if parameter.isArray
645
+ def isArray
646
+ parameter.isArray
647
+ end
648
+
649
+ # Path to me is path to my parent + my name
650
+ #
651
+ # @attr [String:Array] path to me
652
+ def parameter_path_to_me
653
+ parameter_path + [parameter.name]
654
+ end
655
+
656
+ # @!endgroup
657
+
658
+ # ------------------------------------------------------------------
659
+ # @!group Implement set of valid values for StepGeneratorValue
660
+
661
+ # must implement this method in sub-class
662
+ def validValuesSet
663
+ raise "Missing implmementation"
664
+ end
665
+
666
+ # @return [Integer] calculatedCardinality validValues
667
+ def validValuesSetCardinality
668
+ raise "Missing implmementation"
669
+ end
670
+
671
+ # @!endgroup
672
+
673
+ end # class StepGeneratorValueRoot
674
+
675
+ # ------------------------------------------------------------------
676
+ # Class pointing to Parameter_Dom, and generating values
677
+ class StepGeneratorValueRef < StepGeneratorValueRoot
678
+
679
+ # @attr [Sbuilder::StepGenerator] generator producing values for
680
+ # 'super.@parameter'
681
+ attr_accessor :refGenerator
682
+
683
+ # ------------------------------------------------------------------
684
+ # @!group Construct & configure
685
+
686
+
687
+ def initialize( parameter, validators, parameter_path )
688
+ super( parameter, parameter_path )
689
+
690
+ Sbuilder::StepGenerator.logger.info "#{__method__}, StepGeneratorValueRef parameter_path=#{parameter_path}"
691
+ # create refGenerator
692
+ initReference( parameter, validators )
693
+ end
694
+
695
+ # Create 'StepGenerator', and initiliaze it with
696
+ # 'paramsetRef.getResolvedReference'. Sets attribute
697
+ # @refGenerator.
698
+ #
699
+ # @param [Sbuilder::Parameter_Ref] paramsetRef parameter pointint
700
+ # to another parameter set, with which the genarator should be
701
+ # initilized
702
+ #
703
+ private def initReference( paramsetRef, validators )
704
+ self.refGenerator = Sbuilder::StepGenerator.new
705
+ refGenerator.startGenerator( paramsetRef.getResolvedReference, validators, parameter_path_to_me )
706
+ end
707
+
708
+
709
+ # @!endgroup
710
+
711
+ # ------------------------------------------------------------------
712
+ # @!group Implement set of valid values for StepGeneratorValue
713
+
714
+ # Generate array of values using refGenerator.
715
+ #
716
+ # @return [Hash:Array] valid values
717
+ def validValuesSet
718
+
719
+ Sbuilder::StepGenerator.logger.info "#{__method__}, parameter=#{parameter.name}, isArray=#{isArray}, validValuesSetCardinality=#{validValuesSetCardinality}"
720
+
721
+ # ensure that valid values set would not grow too large
722
+ # prior generatring valid the actual set
723
+ Sbuilder::StepGenerator.maxSet( validValuesSetCardinality, parameter )
724
+
725
+ refGenerator.values
726
+
727
+ end
728
+
729
+ # Delegates the task of counting number of elements in the
730
+ # set to '@refGenerator'
731
+ #
732
+ # @return [Integer] calculatedCardinality validValues
733
+ def validValuesSetCardinality
734
+ refGenerator.validValuesSetCardinality
735
+ end
736
+
737
+ # @!endgroup
738
+
739
+ end # class StepGeneratorValueRef < StepGeneratorValueRoot
740
+
741
+
742
+ # ------------------------------------------------------------------
743
+ # Class pointing to Parameter_Dom
744
+ class StepGeneratorValueDomain < StepGeneratorValueRoot
745
+
746
+ # @attr [Lambda] lambda limiting values generated
747
+ attr_accessor :action
748
+
749
+ # @attr [object] validator_context set using validators array
750
+ attr_accessor :action_value
751
+
752
+ # @attr [Boolean] fixedValue if action limit underlying domain to
753
+ # a fixed value
754
+ attr_accessor :fixedValue
755
+
756
+ # ------------------------------------------------------------------
757
+ # @!group Construct & configure
758
+
759
+ #
760
+ # @param [Sbuilder::Parameter] parameter for which to generate
761
+ # values
762
+ #
763
+ # @param [lambda(i,domValue,action_value )] action returns
764
+ # true if domValue accepted
765
+ #
766
+ # @param [object] action_value defined in 'validators' -array
767
+ #
768
+ # @param [String:Array] parameter_path leading to this param
769
+ def initialize( parameter, action, action_value, parameter_path, fixedValue )
770
+ super( parameter, parameter_path )
771
+ self.validIndex = 0
772
+ self.action = action
773
+ self.action_value = action_value
774
+ self.fixedValue = fixedValue
775
+ end
776
+
777
+ # @!endgroup
778
+
779
+ # ------------------------------------------------------------------
780
+ # @!group Implement set of valid values for StepGeneratorValue
781
+
782
+ #
783
+ # Generate array of domain values from resolved domain for
784
+ # '@parameter'. Use @action -lambda to screen domain values which
785
+ # should be included to 'validValues'.
786
+ #
787
+ # @return [String:Array] valid domain values
788
+ #
789
+ def validValuesSet
790
+ Sbuilder::StepGenerator.logger.info "#{__method__}, parameter=#{parameter.name}, isArray=#{isArray}"
791
+
792
+ # return String:Array
793
+ vals = []
794
+ if fixedValue
795
+ # at this time use 'action_value' to access parameter value,
796
+ # may chg later? to smtg better
797
+ val = parameterValue( action_value ) if action_value
798
+ # include to 'vals' if 'action' says yes
799
+ vals << val if action.call( action_value, val, action_value )
800
+ else
801
+
802
+ # not fixed value - need access domain range & filter using actions
803
+
804
+ # normally 0..cardinality, for integer ranges smthg 1..3
805
+ range = retriveParameterRange
806
+ Sbuilder::StepGenerator.logger.debug "#{__method__}: range=#{range}, first=#{range.first}, last=#{range.last}"
807
+
808
+ # not using fixedValue, guard againts ridicilous range
809
+ Sbuilder::StepGenerator.maxSet( range.last - range.first, parameter, 10000 )
810
+ # (0..parameterMaxIndex).to_a.map { |i|
811
+
812
+ vals = range.to_a.map { |i|
813
+ # access domain element for range index
814
+ {
815
+ :i=>i,
816
+ :v=>parameterValue( i )
817
+ }
818
+ }.select { |iv_hash|
819
+ # use action to select what is actually needed
820
+ action.call( iv_hash[:i], iv_hash[:v], action_value )
821
+ }.map { |iv_hash|
822
+ # take value
823
+ iv_hash[:v]
824
+ }
825
+ end
826
+ return vals
827
+
828
+ end
829
+
830
+ # # @return [Integer] number of elements in underlying domain,
831
+ # # including Nil, if it there
832
+ # private def parameterMaxIndex
833
+ # ret = parameter.resolvedDomain.cardinality
834
+ # # Nil NOT included --> take it away
835
+ # ret -= 1 if !parameter.resolvedDomain.includeNil
836
+ # ret
837
+ # end
838
+
839
+
840
+ # @return [String|Integer|false] 'inIndex'-th domain value from
841
+ # resolved domain for '@parameter'
842
+ private def parameterValue( inIndex )
843
+ pv = retriveParameterValue( inIndex )
844
+ # pv = '"' + pv + '"' if pv
845
+ pv
846
+ end
847
+
848
+ # @return [Integer..Integer] range for +parameter.resolvedDomain+
849
+ # to iterate +parameterValue+
850
+ private def retriveParameterRange
851
+ parameter.resolvedDomain.domain_range
852
+ end
853
+
854
+ # @return [String] 'inIndex'-th domain value from resolved domain
855
+ # for the '@parameter'
856
+ private def retriveParameterValue( inIndex )
857
+ parameter.resolvedDomain.render_entry( inIndex )
858
+ end
859
+
860
+
861
+ # Count number of elements in set after domain elements has been
862
+ # filtered. If '@action' chooses fixed value, i.e. when
863
+ # 'fixedValue' == true, return 1
864
+ #
865
+ # @return [Integer] lenght of underlying set, or 1 when fixedValue
866
+ def validValuesSetCardinality
867
+ fixedValue ? 1 : validValuesSet.length
868
+ # validValuesSet.length
869
+ end
870
+
871
+
872
+ # @!endgroup
873
+
874
+ end # class StepGeneratorValueDomain
875
+
876
+ end