tla-sbuilder 0.1.0 → 0.2.1

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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +116 -33
  3. data/VERSION +1 -1
  4. data/lib/cli/cli-customer.rb +41 -23
  5. data/lib/cli/cli-example.rb +1 -1
  6. data/lib/cli/cli-pet.rb +33 -30
  7. data/lib/cli/cli-text.rb +57 -17
  8. data/lib/cli/cli.rb +56 -10
  9. data/lib/sbuilder.rb +3 -1
  10. data/lib/sbuilder/constants.rb +5 -2
  11. data/lib/sbuilder/controller.rb +289 -59
  12. data/lib/sbuilder/default-sbuilder.yaml +25 -3
  13. data/lib/sbuilder/domain.rb +1 -1
  14. data/lib/sbuilder/domain_cardinality.rb +1 -1
  15. data/lib/sbuilder/domain_value.rb +1 -1
  16. data/lib/sbuilder/exception.rb +13 -7
  17. data/lib/sbuilder/extension_loader.rb +75 -18
  18. data/lib/sbuilder/facade/api_loader.rb +293 -0
  19. data/lib/sbuilder/factory.rb +66 -3
  20. data/lib/sbuilder/model.rb +59 -3
  21. data/lib/sbuilder/mustache/template.rb +13 -13
  22. data/lib/sbuilder/mustache/template_reader_context.rb +5 -3
  23. data/lib/sbuilder/param_set.rb +2 -1
  24. data/lib/sbuilder/param_set_db.rb +1 -1
  25. data/lib/sbuilder/param_set_def.rb +1 -1
  26. data/lib/sbuilder/param_set_if.rb +1 -1
  27. data/lib/sbuilder/param_set_loader_swagger.rb +122 -121
  28. data/lib/sbuilder/param_set_step.rb +1 -1
  29. data/lib/sbuilder/parameter.rb +1 -1
  30. data/lib/sbuilder/parameter_container.rb +1 -1
  31. data/lib/sbuilder/parameter_dom.rb +1 -1
  32. data/lib/sbuilder/parameter_ref.rb +2 -2
  33. data/lib/sbuilder/resolver_rule.rb +1 -1
  34. data/lib/sbuilder/resolver_rule_match.rb +1 -1
  35. data/lib/sbuilder/resolver_rule_ref.rb +1 -1
  36. data/lib/sbuilder/spec/README +5 -0
  37. data/lib/sbuilder/spec/api_loader_facade.rb +247 -0
  38. data/lib/utils/cache_lines.rb +21 -0
  39. data/lib/utils/netio.rb +5 -13
  40. data/mustache/cfg/macro_run.mustache +1 -0
  41. data/mustache/interface_processes.mustache +9 -2
  42. data/mustache/interface_stubs_dummy.mustache +7 -0
  43. data/mustache/interface_types.mustache +3 -3
  44. data/mustache/invariant_activate.mustache +16 -0
  45. data/mustache/setup/assumptions_activate.mustache +16 -0
  46. data/mustache/{domains_run.mustache → setup/domains_run.mustache} +2 -2
  47. data/mustache/setup/operator_run.mustache +2 -0
  48. data/mustache/setup/steps_run_bind_set.mustache +1 -1
  49. data/mustache/setup/steps_run_parameterBind.mustache +4 -2
  50. data/mustache/tla/macro_run.mustache +8 -0
  51. data/mustache/tla/operator_run.mustache +1 -0
  52. data/mustache/tla/plc_define_run.mustache +2 -4
  53. data/mustache/tla/plc_run_state.mustache +1 -1
  54. data/src-extend/extend/extend_invariant_cfg.mustache +1 -1
  55. data/src/pet/assumption_domains.tla +1 -1
  56. data/src/pet/correctness.cfg +4 -0
  57. data/tla-sbuilder.gemspec +3 -1
  58. metadata +14 -10
  59. data/lib/sbuilder/param_set_loader.rb +0 -77
  60. data/src-extend/extend_app/correctness.cfg +0 -9
@@ -2,43 +2,78 @@ module Sbuilder
2
2
 
3
3
  class CliText
4
4
 
5
- SBUILDER_RESOLVERS = <<-EOS
5
+ SBUILDER_EXTENSION = <<-EOS.unindent
6
+
7
+ # Load and configure sbuilder plugin extensions
8
+ #
9
+ # SCHEMA
10
+ #
11
+ # extend:
12
+ # loaders:
13
+ # - gem: <gem-name>
14
+ # className: <class name>
15
+ # configuration:
16
+ # <configuration-value>
17
+ #
18
+ # <gem-name>: gem name to require
19
+ # <class name>: name of interface loader in 'type' property in 'interfaces' array
20
+ # <configuration-value>: a (hash) value passed to 'className'::configure' -method
21
+ #
22
+ EOS
23
+
24
+ SBUILDER_INVARIANTS = <<-EOS.unindent
25
+
26
+ # Activate invariant operator defines in sBuilder code repository
27
+ #
28
+ # SCHEMA:
29
+ #
30
+ # invariants:
31
+ # - <invariant-name>: <invariant description>
32
+ #
33
+ #
34
+ # <invariant-name>: name of TlAplus operator defined in sBuilder code repository
35
+ # <invariant description>: documentantion text for the invariant
36
+ #
37
+ EOS
38
+
39
+
40
+
41
+ SBUILDER_RESOLVERS = <<-EOS.unindent
6
42
 
7
43
  # Define how parameter names are mapped to domain
8
44
  #
9
45
  # SCHEMA:
10
46
  #
11
47
  # resolvers:
12
- # - type: <resolver load type>
13
- # file: <file name in cnf-dir>
48
+ # - file: <file name in cnf-dir>
14
49
  # url: <path or url>
15
50
  #
16
- # <resolver load type>: resolver loader type, valid values: [ 'resolver_yaml' ]
51
+ # Give either 'file' or 'url'
17
52
  # <file name in cnf-dir>: file name in cnf-directory
18
53
  # <path or url>: path relative to cwd, or http url
19
54
  #
20
55
  #
21
- # COMMENTS:
22
- # - give 'file' xor 'url' property
23
56
  #
24
57
 
25
58
  EOS
26
59
 
27
- SBUILBER_INTERFACES = <<-EOS
60
+ SBUILBER_INTERFACES = <<-EOS.unindent
28
61
 
29
62
  # Define how to load interfaces configuration
30
63
  #
31
64
  # SCHEMA:
32
65
  #
33
66
  # interfaces:
34
- # - type: <interface loader type>
67
+ # - type: <interface loader name>
35
68
  #
36
69
  # file: <file name in cnf-dir>
37
70
  # infrastructureServices: <is infrastructureService>
38
71
  # url: <path or url>
39
72
  # cache: <cache file path>
40
73
  #
41
- # <interface loader type>: interface loader type, valid values: [ 'swagger' ]
74
+ # <interface loader name>: name of interface loader,
75
+ # valid values: 'swagger' and className values
76
+ # given in 'extend.loaders' array
42
77
  # <is infrastructureService>: true or false (default false)
43
78
  # <file name in cnf-dir> : file name in cnf-directory
44
79
  # <path or url> : path relative to cwd, or http url,
@@ -55,7 +90,7 @@ module Sbuilder
55
90
  EOS
56
91
 
57
92
 
58
- SBUILER_SETUPS = <<-EOS
93
+ SBUILER_SETUPS = <<-EOS.unindent
59
94
 
60
95
  # Define environment setups
61
96
  #
@@ -67,17 +102,21 @@ module Sbuilder
67
102
  # url: <path or url>
68
103
  # preferences:
69
104
  # <hash-values>
105
+ # assumptions:
106
+ # <assume-op-names>
70
107
  #
71
108
  # <setupname> : name of setup = sub directory under <gen_dir>
72
109
  # <file name in cnf-dir>: name extension configurion file in cnf-directory
73
110
  # <path or url> : relative name or url of configurion file
74
111
  # <hash-values> : optional properties overriding global generate preferences
112
+ # <assume-op-names> : array of operator names to put into ASSUME directives
75
113
  #
76
114
  # COMMENTS:
77
115
  # - preferences property is optional
78
116
  EOS
79
117
 
80
- SBUILDER_GENERATE = <<-EOS
118
+ SBUILDER_GENERATE = <<-EOS.unindent
119
+
81
120
  # Generate definitions
82
121
  #
83
122
  # SCHEMA:
@@ -106,13 +145,14 @@ module Sbuilder
106
145
  #
107
146
  EOS
108
147
 
109
- SBUILDER_PREFERENCES = <<-EOS
148
+ SBUILDER_PREFERENCES = <<-EOS.unindent
149
+
110
150
  # Generate preferences
111
151
  #
112
152
  # preferences:
113
153
  # <hash-values>
114
154
  #
115
- # <hash-values> optional properties passes to templates in 'PREFERENCES' -property
155
+ # <hash-values> key-value pairs passed to mustache templates in 'PREFERENCES' -property
116
156
  #
117
157
  # Default templates use following propeties
118
158
  # debug-output: <true/false>, output call message in interface processes, default 'true'
@@ -120,7 +160,7 @@ module Sbuilder
120
160
  EOS
121
161
 
122
162
 
123
- EXTENSION_HEADER_DOM = <<-EOS
163
+ EXTENSION_HEADER_DOM = <<-EOS.unindent
124
164
 
125
165
  # Define extension for domains
126
166
  #
@@ -142,7 +182,7 @@ module Sbuilder
142
182
 
143
183
  EOS
144
184
 
145
- EXTENSION_HEADER_IF = <<-EOS
185
+ EXTENSION_HEADER_IF = <<-EOS.unindent
146
186
 
147
187
  # Define name of extension point for interface
148
188
  #
@@ -158,7 +198,7 @@ module Sbuilder
158
198
 
159
199
  EOS
160
200
 
161
- EXTENSION_HEADER_SETUP = <<-EOS
201
+ EXTENSION_HEADER_SETUP = <<-EOS.unindent
162
202
 
163
203
  # Define environment steps
164
204
  #
@@ -194,7 +234,7 @@ module Sbuilder
194
234
  EOS
195
235
 
196
236
 
197
- RESOLVER_HEADER = <<-EOS
237
+ RESOLVER_HEADER = <<-EOS.unindent
198
238
  # Example of an YAML resolver
199
239
  #
200
240
  # Contains array of hashes
@@ -184,16 +184,39 @@ module Sbuilder
184
184
  shared_options :verbosity
185
185
  shared_options :cnf_dir
186
186
  def list( what )
187
- whats = [ "setups", "setup" ]
188
- raise <<-EOS unless whats.include?( what )
189
- Unknown command 'list #{what}'
187
+ validateWhats( what )
188
+ ctrl = getCtrl
189
+ # puts "#{ctrl.getSetups().map { |setup| setup['setupDirectory']}.join(' ')}"
190
+ puts "#{getSetupNames(ctrl).join(' ')}"
191
+ end
190
192
 
191
- Valid list targets: #{whats.join(',')}
192
- EOS
193
-
194
- ctrl = getController( options )
195
- ctrl.load
196
- puts "#{ctrl.getSetups().map { |setup| setup['setupDirectory']}.join(' ')}"
193
+
194
+ desc "document [setup]", "Document configuration for all setups or for the given setup"
195
+ shared_options :verbosity
196
+ shared_options :cnf_dir
197
+ def document( what=nil )
198
+ controller = getCtrl
199
+ controller.load
200
+
201
+ validateWhats( what, getSetupNames(controller) ) if what
202
+
203
+ invariants = controller.templateData('invariants')['invariants']
204
+ puts "INVARIANTS:"
205
+ invariants.each do |invariant|
206
+ puts <<-EOS.unindent
207
+ - #{invariant[:name]}: #{invariant[:desc]}
208
+ EOS
209
+ end
210
+ puts "SETUPS:"
211
+ controller.processSetups( what ) do |setupName, setupConf, possibilities|
212
+ assumptions = controller.getSetupAssumptionList( setupConf )
213
+ puts <<-EOS.unindent
214
+ - #{setupName}: #{setupConf['desc']}
215
+ - possibilities: #{(setupConf['possibilities'] || [] ).join( ' ' )}
216
+ - assumptions: #{assumptions.join( ' ' )}
217
+ - interfaces: #{controller.templateData('steps' )['steps'].map {|step| step[:interface_operation] }.uniq.join( ' ' )}
218
+ EOS
219
+ end
197
220
  end
198
221
 
199
222
 
@@ -202,6 +225,22 @@ module Sbuilder
202
225
  # common routines
203
226
  no_commands do
204
227
 
228
+ # ensure that 'what' is correct
229
+ def validateWhats( what, whats = [ "setups", "setup" ] )
230
+ raise <<-EOS unless whats.include?( what )
231
+ Unknown target '#{what}'
232
+
233
+ Valid targets: #{whats.join(',')}
234
+ EOS
235
+
236
+ end
237
+
238
+ # @return [Sbuilder::Controller] contrller, which has loader configurations
239
+ def getCtrl
240
+ ctrl = getController( options )
241
+ return ctrl
242
+ end
243
+
205
244
  # Copy 'extendFile' file to 'dirPath', append {{>benchmark/basename(extendFile}}
206
245
  #
207
246
  # @param dirPath [String] directory where extension file created
@@ -240,6 +279,12 @@ module Sbuilder
240
279
 
241
280
  end
242
281
 
282
+ # @param controller [Sbuilder::Controller] controller to read the setups
283
+ # @return [String:Array] names of setups defined in 'ctrl'
284
+ def getSetupNames( ctrl )
285
+ ctrl.getSetups().map { |setup| setup['setupDirectory'] }
286
+ end
287
+
243
288
  # ------------------------------------------------------------------
244
289
 
245
290
  def init_files( options )
@@ -247,7 +292,8 @@ module Sbuilder
247
292
  [
248
293
  { :file => "#{options[:cnf_dir]}/#{Sbuilder::Constants::CNF_FILE }.example", :content => [ Sbuilder::CliCustomer::SBUILDER_YAML_CUSTOMER] },
249
294
  { :file => "#{options[:cnf_dir]}/#{Sbuilder::CliCustomer::FILE_RESOLVER_CUSTOMER}.example", :content => [ Sbuilder::CliCustomer::RESOLVER_CUSTOMER] },
250
- { :file => "#{options[:cnf_dir]}/#{Sbuilder::CliCustomer::FILE_EXTENSIONS_CUSTOMER_COMMON}.exmaple", :content => [Sbuilder::CliCustomer::EXTENSIONS_CUSTOMER_COMMON] },
295
+ { :file => "#{options[:cnf_dir]}/#{Sbuilder::CliCustomer::FILE_EXTENSIONS_CUSTOMER_COMMON}.example", :content => [Sbuilder::CliCustomer::EXTENSIONS_CUSTOMER_COMMON] },
296
+ { :file => "#{options[:cnf_dir]}/#{Sbuilder::CliCustomer::FILE_EXTENSIONS_CUSTOMER_IF}.example", :content => [Sbuilder::CliCustomer::EXTENSIONS_CUSTOMER_IF] },
251
297
  { :file => "#{options[:cnf_dir]}/#{Sbuilder::CliCustomer::FILE_EXTENSIONS_CUSTOMER_RUN1}.example", :content => [Sbuilder::CliCustomer::EXTENSIONS_CUSTOMER_RUN1] },
252
298
  { :file => "#{options[:cnf_dir]}/#{Sbuilder::CliCustomer::FILE_EXTENSIONS_CUSTOMER_RUN2}.example", :content => [Sbuilder::CliCustomer::EXTENSIONS_CUSTOMER_RUN2] },
253
299
  { :file => "#{options[:cnf_dir]}/#{Sbuilder::CliCustomer::FILE_INTERFACE_CUSTOMER}.example", :content => [Sbuilder::CliCustomer::INTERFACE_CUSTOMER_SWAGGER] },
@@ -4,6 +4,7 @@ require_relative "utils/string_inject"
4
4
 
5
5
  require_relative "utils/version"
6
6
  require_relative "utils/logger"
7
+ require_relative "utils/cache_lines"
7
8
  require_relative "utils/netio"
8
9
 
9
10
  require_relative "sbuilder/constants.rb"
@@ -36,7 +37,7 @@ require_relative "sbuilder/resolver.rb"
36
37
  require_relative "sbuilder/resolver_loader.rb"
37
38
  require_relative "sbuilder/resolver_loader_yaml.rb"
38
39
 
39
- require_relative "sbuilder/param_set_loader.rb"
40
+
40
41
  require_relative "sbuilder/param_set_loader_swagger.rb"
41
42
 
42
43
  require_relative "sbuilder/model.rb"
@@ -46,6 +47,7 @@ require_relative "sbuilder/extension_loader.rb"
46
47
  require_relative "sbuilder/factory.rb"
47
48
  require_relative "sbuilder/controller.rb"
48
49
 
50
+ require_relative "sbuilder/facade/api_loader.rb"
49
51
 
50
52
  require_relative "sbuilder/mustache/template_reader"
51
53
  require_relative "sbuilder/mustache/template_reader_context"
@@ -11,10 +11,13 @@ module Sbuilder
11
11
  EXTENSION_LOADER_YAML = "default-yaml"
12
12
 
13
13
  # supported paramter set types
14
- SWAGGER = "swagger"
14
+ INTERFACE_OPERATION = "operation"
15
15
  SWAGGER_DEFINITION="definition"
16
16
  PARAM_SET_STEPS = "steps"
17
17
 
18
+ # supported interfa loader
19
+ LOADER_SWAGGER = "swagger"
20
+
18
21
  # supported mapper types
19
22
  MAPPER_YAML = "resolver_yaml"
20
23
 
@@ -47,7 +50,7 @@ module Sbuilder
47
50
  CNF_FILE="sbuilder.yaml"
48
51
 
49
52
  # directory to cache loaded files
50
- CACHE_DIR = "tmp"
53
+ CACHE_DIR = "cache"
51
54
 
52
55
  # direcotory where to output rendered templates
53
56
  GEN_DIR = "gen"
@@ -13,8 +13,8 @@ module Sbuilder
13
13
 
14
14
  # model parts
15
15
  attr_reader :model # which contain values loaded
16
- def_delegators :model, :extendDomain, :extendInterface, :interfaceEncountered, :definitionEncountered,
17
- :domainEncountered, :templateData, :getInterface, :extendStep
16
+ def_delegators :model, :extendDomain, :extendInterface, :modelInterface, :modelDefinition,
17
+ :domainEncountered, :templateData, :getInterface, :extendStep, :defineSetup
18
18
 
19
19
  def_delegators :factory, :createParameter, :createParamSet
20
20
 
@@ -30,16 +30,35 @@ module Sbuilder
30
30
 
31
31
 
32
32
  @@validSetups_required = [ "setupDirectory", ]
33
- @@validSetups_allowed = @@validSetups_required + [ 'extensions', "desc", "preferences", "possibilities" ]
33
+ @@validSetups_allowed = @@validSetups_required + [ 'extensions', "desc", "preferences", "possibilities", 'assumptions', 'configuration']
34
+ @@validSetupConfiguration_required = []
35
+ @@validSetupConfiguration_allowed = ['allow_domain_nil_values']
34
36
 
35
- @@extensionLoaderDef_required = ['type' ]
36
- @@extensionLoaderDef_oneof = ["url", "file"]
37
- @@extensionLoaderDef_allowed = @@extensionLoaderDef_required + @@extensionLoaderDef_oneof
37
+
38
+ @@extensionLoaderDef_required = [ ]
39
+ @@extensionLoaderDef_oneof = ["url", "file",]
40
+ @@extensionLoaderDef_defaults = {
41
+ 'type' => Sbuilder::Constants::EXTENSION_LOADER_YAML
42
+ }
43
+ @@extensionLoaderDef_allowed = @@extensionLoaderDef_required + @@extensionLoaderDef_oneof + ['type']
38
44
 
39
- @@interfaceLoaderDef_required = ['type',]
40
- @@interfaceLoaderDef_oneof = [ 'url', "file", ]
41
- @@interfaceLoaderDef_allowed = @@interfaceLoaderDef_required + ["cache", "infrastructureServices" ] + @@interfaceLoaderDef_oneof
45
+
46
+ @@resolverLoader_required = [ ]
47
+ @@resolverLoader_oneof = ["url", "file",]
48
+ @@resolverLoader_defaults = {
49
+ 'type' => Sbuilder::Constants::MAPPER_YAML
50
+ }
51
+ @@resolverLoader_allowed = @@resolverLoader_required + @@resolverLoader_oneof + ['type']
42
52
 
53
+ @@interfaceLoaderDef_required = [ ]
54
+ @@interfaceLoaderDef_oneof = [ 'url', "file", ]
55
+ @@interfaceLoaderDef_oneof2 = [ 'type', "className", ]
56
+ @@interfaceLoaderDef_allowed = @@interfaceLoaderDef_required + ["cache", "infrastructureServices", "namespace" ] + @@interfaceLoaderDef_oneof + @@interfaceLoaderDef_oneof2
57
+
58
+ @@validExtendLoader = %w( gem className configuration )
59
+
60
+ @@validConfig = %w( generate )
61
+ @@allowConfig = @@validConfig + %w( extend extensions setups preferences resolvers interfaces invariants )
43
62
 
44
63
  @@validGenerateConfigs = ["output", "inputs"]
45
64
  @@allowedGenerateConfigs = @@validGenerateConfigs + ['category']
@@ -69,10 +88,17 @@ module Sbuilder
69
88
  :filter_src => options[:filter_src] || false,
70
89
  :templates => options[:templates],
71
90
  } #.merge( options[PROGNAME] || {} )
72
- @factory = factory
91
+ setFactory( factory )
73
92
  start
74
93
  end
75
94
 
95
+ # @param factory [Sbuilder::Factory] to build objects
96
+ def setFactory( factory )
97
+ @factory = factory
98
+ # add loaders configured in 'sbuilder.yaml'
99
+ factory.addLoaders( getConfiguredLoaders )
100
+ end
101
+
76
102
  # @param possibilities [String:Array] possibilities defined in setup
77
103
  def start
78
104
  # init state
@@ -81,11 +107,62 @@ module Sbuilder
81
107
 
82
108
  end
83
109
 
110
+ # Iterate 'assumptions' and add to model assumption descritptions.
111
+ # Issue a warning if assumptions not defined
112
+ #
113
+ # @param assumption [String:Array] name of assumption to activate
114
+
115
+
116
+ def loadAssumptions( assumptions )
117
+
118
+ @logger.info "#{__method__}: assumptions=#{assumptions}"
119
+ assumptions.each do |assumption|
120
+ model.addAssumption( { :name => assumption, :desc => "Assume #{assumption}" } )
121
+ end # else - not nil
122
+ end
123
+
124
+ # Iterate 'invariants' and add to model invariant descritptions.
125
+ # Isse a warning if invarients not defined
126
+ #
127
+ # @param invariants [Hash:Array] with properties 'key'=>'description'
128
+
129
+ def loadInvariants( invariants )
130
+
131
+ if invariants.nil? then
132
+ msg = <<-EOS
133
+ No invariants section defined in #{getConfigFilePath}.
134
+
135
+ Suggestion add section 'invariants' defining invariants.
136
+ For example:
137
+
138
+ invariants:
139
+ - MustNotHappen: Invariant 'MustNotHappen' verified in the model
140
+
141
+ EOS
142
+ warn msg
143
+ else
144
+ @logger.info "#{__method__}: invariants=#{invariants}"
145
+ invariants = [invariants] if invariants.is_a?( Hash )
146
+ invariants.each do |invariant|
147
+ invariant.each do |k,v|
148
+ model.addInvariant( { :name => k, :desc => v } )
149
+ end
150
+ end
151
+ end # else - not nil
152
+ end
153
+
84
154
  # ------------------------------------------------------------------
85
155
  # build controller: load (domain) resolvers
156
+ # @param arrOfmappersTypePath [Hash:Array] of :type,:url
86
157
 
87
158
  def loadResolvers( arrOfmappersTypePath )
88
159
  !arrOfmappersTypePath.nil? && arrOfmappersTypePath.each do |mapperDef|
160
+ # add defaults to 'mapperDef'
161
+ mapperDef = defaultProps( mapperDef, @@resolverLoader_defaults )
162
+ validateProperties( mapperDef, @@resolverLoader_required, @@resolverLoader_allowed )
163
+ validateOne( mapperDef, @@resolverLoader_oneof )
164
+
165
+
89
166
  @logger.debug( "#{__method__} mapperDef=#{mapperDef} " )
90
167
 
91
168
  # find correct loader based on type
@@ -112,12 +189,21 @@ module Sbuilder
112
189
  # ------------------------------------------------------------------
113
190
  # load extensions
114
191
 
115
- # create load && add let it load
116
- def loadExtensions( arrayOfExtensionDefs )
192
+ # Load exntesion for setup
193
+ #
194
+ # @param setupName [String] name of setup, currently = extensionDirectory
195
+ # def loadExtensions( arrayOfExtensionDefs )
196
+ def loadExtensions( setupName )
197
+
198
+ # access sbuilder.yaml configuration
199
+ arrayOfExtensionDefs = getSetupExtensions( setupName )
117
200
 
201
+ # iteratio
118
202
  arrayOfExtensionDefs && arrayOfExtensionDefs.each do |extensionLoaderDef|
119
203
  validateProperties( extensionLoaderDef, @@extensionLoaderDef_required, @@extensionLoaderDef_allowed )
120
204
  validateOne( extensionLoaderDef, @@extensionLoaderDef_oneof )
205
+ # ensure defaults in properties
206
+ extensionLoaderDef = defaultProps( extensionLoaderDef, @@extensionLoaderDef_defaults )
121
207
 
122
208
 
123
209
  @logger.info( "#{__method__} extensionLoaderDef=#{extensionLoaderDef}" )
@@ -127,7 +213,7 @@ module Sbuilder
127
213
  rescue Exception => ee
128
214
  msg = "Error #{ee} caused by #{ee.backtrace.join("\n")} when loading '#{extensionLoaderDef['url']}'\n\n"
129
215
  @logger.error( "#{__method__} #{msg}" )
130
- raise ControllerException.new msg
216
+ raise ControllerException.new, msg, ee.backtrace
131
217
  end
132
218
  end
133
219
  # domainLoader = factory.get
@@ -135,26 +221,73 @@ module Sbuilder
135
221
 
136
222
  # ------------------------------------------------------------------
137
223
  # load interfaces
224
+
225
+ # @param arrOfparamsetTypePath [Hash:Array] of :type,:file|:url,:cache properties
138
226
 
139
227
  def loadInterfaces( arrOfparamsetTypePath )
140
228
  !arrOfparamsetTypePath.nil? && arrOfparamsetTypePath.each do |interfaceParamsetDef|
141
229
 
142
- validateProperties( interfaceParamsetDef, @@interfaceLoaderDef_required, @@interfaceLoaderDef_allowed )
143
- validateOne( interfaceParamsetDef, @@interfaceLoaderDef_oneof )
144
-
230
+ begin
231
+ validateProperties( interfaceParamsetDef, @@interfaceLoaderDef_required, @@interfaceLoaderDef_allowed )
232
+ validateOne( interfaceParamsetDef, @@interfaceLoaderDef_oneof )
233
+ validateOne( interfaceParamsetDef, @@interfaceLoaderDef_oneof2 )
234
+ rescue ControllerException => e
235
+ msg = <<-EOS
236
+ Error:
237
+
238
+ #{e}
239
+
240
+ in
241
+
242
+ #{interfaceParamsetDef.to_yaml}
243
+
244
+
245
+ EOS
246
+ @logger.error( "#{__method__} #{msg}" )
247
+ raise ControllerException.new, msg, e.backtrace
248
+ end
249
+ warn <<-EOS if interfaceParamsetDef['type']
250
+ Interface loader configuration
251
+
252
+ #{interfaceParamsetDef.to_yaml}
253
+
254
+ uses property 'type', which is depracted.
255
+
256
+
257
+
258
+ Use property 'className' instead.
259
+
260
+ Particularly
261
+
262
+ type: #{Sbuilder::Constants::LOADER_SWAGGER}
263
+
264
+ should be replaced with
265
+
266
+ className: Sbuilder::ParamSetLoaderSwagger
267
+
268
+ EOS
145
269
 
146
270
  # find correct loader based on type & configure it
147
271
  loader = factory.getParamSetLoader( getParamsetType( interfaceParamsetDef ))
148
- loader.configure( interfaceParamsetDef )
272
+
273
+ # configure facade && pass it to loader
274
+ facade = factory.getFacade(self)
275
+ # facada loading instrcture services
276
+ facade.configureInfrastructureService( interfaceParamsetDef['infrastructureServices'] == true )
277
+ # facade creates definitions in 'namespace' (default nil = no group)
278
+ facade.configureNamespace( interfaceParamsetDef['namespace'] )
279
+ facade.setInterfaceCacheFilePath(getParamsetCacheFilePath(interfaceParamsetDef))
280
+ loader.setFacade( facade )
281
+
149
282
  # load an put array
150
- loader.load( self, getFileUrlOrPath( interfaceParamsetDef ), getParamsetCacheFilePath(interfaceParamsetDef) )
283
+ loader.load( getFileUrlOrPath( interfaceParamsetDef ), )
151
284
  # @paramSets = paramSets.concat( loaded ) if loaded && loaded.any?
152
285
  end
153
286
  end
154
287
 
155
288
  # # accept parameters set to model
156
- # def interfaceEncountered( paramSet )
157
- # model.interfaceEncountered( paramSet )
289
+ # def modelInterface( paramSet )
290
+ # model.modelInterface( paramSet )
158
291
  # end
159
292
 
160
293
  # def paramSets
@@ -180,12 +313,13 @@ module Sbuilder
180
313
  @logger.info( "#{__method__} load started" )
181
314
  loadResolvers( getResolversConfig )
182
315
  loadInterfaces( getInterfaceConfig )
316
+ loadInvariants( getInvariantConfig )
183
317
  end
184
318
 
185
319
 
186
- def extend
187
- loadExtensions( getExtensionConfigs )
188
- end
320
+ # def extend
321
+ # loadExtensions( getExtensionConfigs )
322
+ # end
189
323
 
190
324
  # ------------------------------------------------------------------
191
325
  # iterate setups
@@ -201,14 +335,15 @@ module Sbuilder
201
335
 
202
336
  validateProperties( setupDef, @@validSetups_required, @@validSetups_allowed )
203
337
  @logger.info( "#{__method__} -->next" ) if setupDirectory && (setupDef['setupDirectory'] != setupDirectory)
204
- next if setupDirectory && setupDef['setupDirectory'] != setupDirectory
338
+ next if setupDirectory && setupDef['setupDirectory'] != setupDirectory
339
+ validateProperties( setupDef['configuration'], @@validSetupConfiguration_required, @@validSetupConfiguration_allowed ) if setupDef['configuration']
205
340
 
206
341
  # process one setupDirectory
207
342
  @logger.info( "#{__method__} start to generate setupDirectory=#{setupDirectory} for #{setupDef}" )
208
343
 
209
344
  output( 1, "------------------------------------------------------------------" ) if isOptFilterSrc
210
345
  output( 1, "generate setup: #{setupDef['setupDirectory']}" )
211
- generate( setupDef['setupDirectory'], setupDef['setupDirectory'], setupDef['extensions'], setupDef['possibilities'] )
346
+ generate( setupDef['setupDirectory'], setupDef['setupDirectory'] )
212
347
  @logger.info( "#{__method__} done to generate setupDirectory=#{setupDirectory} for #{setupDef}" )
213
348
  output( 2, "\n" )
214
349
 
@@ -253,6 +388,10 @@ module Sbuilder
253
388
  # delegate action
254
389
  begin
255
390
  resolver.resolveDomains( paramSet, model )
391
+
392
+ # resolve also response
393
+ resolver.resolveDomains( paramSet.response, model ) if paramSet.respond_to?( :response )
394
+
256
395
  rescue ResolverException => e
257
396
  msg = "Error '#{e}' when mapping domains for parameter set '#{paramSet.getId}'"
258
397
  puts msg
@@ -272,11 +411,48 @@ module Sbuilder
272
411
  #
273
412
  # @param setupName [String] name of setup, currently = extensionDirectory
274
413
  # @param extensionDirectory [String] directory where setup generated
275
- # @arrayOfExtensionDefs [Hash:Array] of extenstions to load
276
414
 
277
- def generate( setupName="default", extensionDirectory="default", arrayOfExtensionDefs=[], possibilities=[] )
415
+ def generate( setupName="default", extensionDirectory="default" )
278
416
  @logger.info( "#{__method__} setupName=#{setupName}, extensionDirectory=#{extensionDirectory}" )
279
- @logger.debug( "#{__method__} arrayOfExtensionDefs=#{arrayOfExtensionDefs}, possibilities=#{possibilities}" )
417
+
418
+ processSetup( setupName ) do |name, setupConf, possibilities|
419
+
420
+ # config && get renderes
421
+ mustache = prepareRender( setupName )
422
+
423
+ # path to directory where setup output is done
424
+ directoryPath = prepareSetupDir( extensionDirectory )
425
+
426
+ # output 'normal templates' - one generate def/one output
427
+ generateCase( setupName, directoryPath, nil, mustache )
428
+
429
+ # For 'possibities': map array of possibilities to array
430
+ # of filenames created using an output -property on
431
+ # 'generate' definition
432
+ possibilities && possibilities.any? && generateCase( setupName, directoryPath, 'possibility', mustache ) do |output|
433
+ # use output as template rendering
434
+ possibilities.map do |p|
435
+ {
436
+ :possibility => p,
437
+ :outputFile => mustache.render_str( output, { "possibility" => p } ),
438
+ }
439
+ end # map
440
+ end
441
+
442
+ end
443
+
444
+ end
445
+
446
+ # @param chosenSetup [String] optional string for the setup to process
447
+ def processSetups(chosenSetup=nil, &blk )
448
+ setups = Marshal.load( Marshal.dump( getSetups ) || [] ).select { |s| chosenSetup.nil? || s['setupDirectory'] == chosenSetup }
449
+ setups.each do |setup|
450
+ setupName = setup['setupDirectory']
451
+ processSetup( setupName, &blk )
452
+ end
453
+ end
454
+
455
+ def processSetup( setupName, &blk )
280
456
 
281
457
  # init state
282
458
  start
@@ -287,35 +463,24 @@ module Sbuilder
287
463
  # resolve domain
288
464
  resolve
289
465
 
466
+ # access config && put to model
467
+ setupConf = getSetup( setupName )
468
+ defineSetup( setupConf )
469
+
470
+ # add assumptions to model
471
+ loadAssumptions( getSetupAssumptionList( setupConf ) )
472
+
290
473
  # extensions
291
- loadExtensions( arrayOfExtensionDefs )
474
+ loadExtensions( setupName )
292
475
 
293
476
  # config model - before config rendering
477
+ possibilities= getSetupPossibilitiesList( setupName )
294
478
  model.setPossibilities( possibilities )
295
-
296
- # config && get renderes
297
- mustache = prepareRender( setupName )
298
479
 
299
- # path to directory where setup output is done
300
- directoryPath = prepareSetupDir( extensionDirectory )
301
-
302
- # output 'normal templates' - one generate def/one output
303
- generateCase( setupName, directoryPath, nil, mustache )
304
-
305
- # For 'possibities': map array of possibilities to array
306
- # of filenames created using an output -property on
307
- # 'generate' definition
308
- possibilities && generateCase( setupName, directoryPath, 'possibility', mustache ) do |output|
309
- # use output as template rendering
310
- possibilities.map do |p|
311
- {
312
- :possibility => p,
313
- :outputFile => mustache.render_str( output, { "possibility" => p } ),
314
- }
315
- end # map
316
- end
480
+ yield setupName, setupConf, possibilities
317
481
 
318
482
  end
483
+
319
484
 
320
485
 
321
486
  # Ensure that directory 'extensionDirectory' exists under
@@ -505,7 +670,7 @@ module Sbuilder
505
670
  #
506
671
  # @param modelData [String] type of data (see model#templateData)
507
672
  #
508
- # @param d [Hash] data element, content depends on 'modelData'
673
+ # @param renderData [Hash] data element to filter, content depends on 'modelData'
509
674
  #
510
675
  # @return [Boolean] true when show the elmement
511
676
  def setupFilter( modelData, renderData )
@@ -582,10 +747,24 @@ module Sbuilder
582
747
  return setupPossis
583
748
  end
584
749
 
585
- # create data to pass to template generateion
586
- # def templateData
587
- # return model.templateData
588
- # end
750
+
751
+
752
+ # Return model invariant defined in sbuilder
753
+ #
754
+ # @return [String:Array] of invariant names
755
+ def getModelInvariants
756
+ names = []
757
+ getInvariantConfig.each { |invariant| names += invariant.keys }
758
+ @logger.info "#{__method__} invariants=#{names.join(',')}"
759
+ return names
760
+ end
761
+
762
+
763
+ # @return [String:Array] names of setup assumes from
764
+ # 'setups.{supet}.assumptions' property
765
+ def getSetupAssumes
766
+ model.assumptions.map{|a| a[:name] }
767
+ end
589
768
 
590
769
  # ------------------------------------------------------------------
591
770
  # configuration
@@ -611,7 +790,8 @@ module Sbuilder
611
790
 
612
791
  @logger.debug( "#{__method__} config in #{getInternalConfigFilePath} internal_config= #{internal_config.to_yaml}" )
613
792
  @controller_config['generate'] = @controller_config['generate'] + internal_config['generate']
614
- @logger.debug( "#{__method__} @controller_config=#{@controller_config.to_yaml}" )
793
+ @logger.debug( "#{__method__} @controller_config=#{@controller_config.to_yaml}" )
794
+ validateProperties( @controller_config, @@validConfig, @@allowConfig )
615
795
  @controller_config
616
796
  end
617
797
 
@@ -626,6 +806,25 @@ module Sbuilder
626
806
  @logger.debug( "#{__method__} setupName=#{setupName}, setup=#{setup} " )
627
807
  setup
628
808
  end
809
+
810
+ # @return [Hash:Array] of 'type', 'url'|'file' properties
811
+ def getSetupExtensions( setupName )
812
+ @logger.debug( "#{__method__} setupName=#{setupName}" )
813
+ getSetup( setupName )['extensions'] || []
814
+ end
815
+
816
+ # @return [String:Array] of setup possibilities
817
+ def getSetupPossibilitiesList( setupName )
818
+ @logger.debug( "#{__method__} setupName=#{setupName}" )
819
+ getSetup( setupName )['possibilities'] || []
820
+ end
821
+
822
+ # @param setupDef [Hash] setup configuration
823
+ # @return [String:Array] name of assumption in setup, [] if none
824
+ def getSetupAssumptionList( setupDef )
825
+ return setupDef['assumptions'] || []
826
+ end
827
+
629
828
 
630
829
 
631
830
  def getPreferencesData( setupName )
@@ -680,11 +879,34 @@ module Sbuilder
680
879
  getConfig()['extensions']
681
880
  end
682
881
 
882
+ # @return [Hash] of extension properties
883
+ def getExtensions
884
+ getConfig()['extend'] || {}
885
+ end
886
+
887
+ # Api loaders configured in sbuilder.yaml['extend']['loaders']
888
+ #
889
+ # @return [Hash:Array] with :name,:className,:configuration properties
890
+ def getConfiguredLoaders
891
+ loaders = getExtensions()['loaders'] || []
892
+ loaders.each do |loader|
893
+ validateProperties( loader, @@validExtendLoader )
894
+ end
895
+ loaders
896
+ end
683
897
 
684
898
  def getResolversConfig
685
899
  getConfig()['resolvers']
686
900
  end
687
901
 
902
+ # @return [Hash:Array] of invariants defined
903
+ def getInvariantConfig
904
+ invariants = getConfig()['invariants']
905
+ invariants = [invariants] if invariants.is_a?( Hash )
906
+ return invariants || []
907
+ end
908
+
909
+
688
910
  # @param generateCategory [Nil|String] choose templates in
689
911
  # 'generateCategory', @return [Hash:Array] of {'output', 'inputs'}
690
912
  # defining a file to render using templates in 'inputs'
@@ -717,15 +939,16 @@ module Sbuilder
717
939
 
718
940
  end
719
941
 
720
- # return optional cacheFilePath from paramSetDef, nil if no 'cache' -property
942
+ # @return [String] path to cacheFilePath, if no 'cache' -property
721
943
  def getParamsetCacheFilePath( paramSetDef )
722
944
  return "#{getOpt(:cache_dir)}/#{paramSetDef['cache']}" if paramSetDef['cache'] && getOpt(:cache_dir)
723
945
  return paramSetDef['cache'] if paramSetDef['cache']
724
946
  return nil
725
947
  end
726
-
948
+
949
+ # @return [String] loader type (className/type)
727
950
  def getParamsetType( paramSetDef )
728
- paramSetDef['type']
951
+ paramSetDef['className'] ? paramSetDef['className'] : paramSetDef['type']
729
952
  end
730
953
 
731
954
  # def getResolverDefPath( mapperDef )
@@ -790,6 +1013,13 @@ module Sbuilder
790
1013
  private def validateOne( defintionHash, propList )
791
1014
  raise ControllerException.new "Must give one #{propList} in #{defintionHash}" unless propList.select {|prop| defintionHash.has_key?(prop) }.length == 1
792
1015
  end
1016
+
1017
+ # add default properties in 'defaults' to 'defintionHash'
1018
+ private def defaultProps( defintionHash, defaults )
1019
+ defintionHash = defintionHash.merge( defaults ) do |k,orig,default|
1020
+ orig.nil? ? default : orig
1021
+ end
1022
+ end
793
1023
 
794
1024
 
795
1025