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
@@ -1,3 +1,4 @@
1
+ # coding: utf-8
1
2
  require 'forwardable'
2
3
 
3
4
  module Sbuilder
@@ -5,18 +6,46 @@ module Sbuilder
5
6
  class Controller
6
7
 
7
8
 
8
-
9
9
  extend Forwardable # for easy delegation
10
10
 
11
- attr_reader :factory # factory pattern
12
- attr_reader :mappers # array of loader 'Resolver' objects
11
+ # @attr [Factory] factory
12
+ attr_reader :factory
13
+
14
+ # @əttr [Resolver] mappers array of loader 'Resolver' objects
15
+ attr_reader :mappers
13
16
 
14
- # model parts
15
- attr_reader :model # which contain values loaded
16
- def_delegators :model, :extendDomain, :extendInterface, :modelInterface, :modelDefinition,
17
- :domainEncountered, :templateData, :getInterface, :extendStep, :defineSetup
17
+ # @attr partials [Hash] map extension-point to array of partial templates
18
+ # @option partials [String] :key name of extension point
19
+ # @option partials [String] :value array of partials to include
20
+ attr_reader :partials
21
+
22
+ # @attr [Hash] updatedSetups
23
+ #
24
+ # @option updatedSetups [String] <key> setupName being extended
25
+ #
26
+ # @option updatedSetups [Hash] <value> to merge to setup
27
+ # configuration
28
+ attr_reader :updatedSetups
29
+
30
+ # @attr [Model] model
31
+ attr_reader :model
18
32
 
19
- def_delegators :factory, :createParameter, :createParamSet
33
+ def_delegators :model,
34
+ :extendDomain,
35
+ :extendInterface,
36
+ :modelInterface,
37
+ :modelDefinition,
38
+ :domainEncountered,
39
+ :addApplicationDomainValue,
40
+ :templateData,
41
+ :getInterface,
42
+ :getSymbolTable,
43
+ :extendStep
44
+
45
+ def_delegators :factory,
46
+ :createParameter,
47
+ :createParamSet,
48
+ :getResolverLoader
20
49
 
21
50
 
22
51
 
@@ -42,6 +71,9 @@ module Sbuilder
42
71
  }
43
72
  @@extensionLoaderDef_allowed = @@extensionLoaderDef_required + @@extensionLoaderDef_oneof + ['type']
44
73
 
74
+ @@snippetLoader_required = [ 'metatype', 'appName', 'file' ]
75
+ @@snippetLoader_allowed = @@snippetLoader_required + []
76
+
45
77
 
46
78
  @@resolverLoader_required = [ ]
47
79
  @@resolverLoader_oneof = ["url", "file",]
@@ -50,26 +82,38 @@ module Sbuilder
50
82
  }
51
83
  @@resolverLoader_allowed = @@resolverLoader_required + @@resolverLoader_oneof + ['type']
52
84
 
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
85
 
60
86
  @@validConfig = %w( generate )
61
- @@allowConfig = @@validConfig + %w( extend extensions setups preferences resolvers interfaces invariants )
87
+ @@allowConfig = @@validConfig + %w( extend extensions setups preferences resolvers interfaces invariants snippets )
88
+
89
+ @@extend_required = %w( )
90
+ @@extend_allowed = @@extend_required + %w( loaders )
62
91
 
63
92
  @@validGenerateConfigs = ["output", "inputs"]
64
93
  @@allowedGenerateConfigs = @@validGenerateConfigs + ['category']
65
94
  @@validGenerateDef_required = [ "template", "desc", "modelData" ]
66
- @@validGenerateDef_allowed = @@validGenerateDef_required + [ "templateParameters" ]
95
+ @@validGenerateDef_allowed = @@validGenerateDef_required + [ "templateParameters", 'type', 'symbols' ]
96
+
97
+ # moved to Constants::VALIDATION
98
+ # @@requireExtendLoader = %w( className configuration )
99
+ # @@allowExtendLoader = %w( gem objects ) + @@requireExtendLoader
100
+
101
+ # @@snippetLoaders_required = ['className', 'snippets' ]
102
+ # @@snippetLoaders_allowed = @@snippetLoaders_required + []
103
+
104
+ # @@interfaceLoaderDef_required = [ ]
105
+ # @@interfaceLoaderDef_oneof = [ 'url', "file", ]
106
+ # @@interfaceLoaderDef_oneof2 = [ 'type', "className", ]
107
+ # @@interfaceLoaderDef_allowed = @@interfaceLoaderDef_required + ["cache", "infrastructureServices", "namespace" ] + @@interfaceLoaderDef_oneof + @@interfaceLoaderDef_oneof2
108
+
109
+
110
+
67
111
  # ------------------------------------------------------------------
68
112
  # mixer
69
- PROGNAME = "Controller" # progname for logger
70
- include Sbuilder::Utils::MyLogger # mix logger
71
-
113
+ PROGNAME = nil # progname for logger default class name
114
+ include Sbuilder::Utils::MyLogger # mix logger
72
115
 
116
+ include Sbuilder::ControllerUtils
73
117
  # ------------------------------------------------------------------
74
118
  # constructore
75
119
 
@@ -86,9 +130,15 @@ module Sbuilder
86
130
  :cnf_file => options[:cnf_file] || Sbuilder::Constants::CNF_FILE,
87
131
  :verbosity => options[:verbosity].nil? ? Sbuilder::Constants::OPT_VERBOSITY : options[:verbosity],
88
132
  :filter_src => options[:filter_src] || false,
89
- :templates => options[:templates],
133
+ :templates => options[:templates] || [ Sbuilder::Constants::SRC_PATH],
134
+ :default_templates => options[:default_templates] || [Sbuilder::Constants::TEMPLATE_GEM],
90
135
  } #.merge( options[PROGNAME] || {} )
91
136
  setFactory( factory )
137
+
138
+ # populated in 'resolveExtensionPartials'
139
+ @partials = initPartials
140
+
141
+ # reset controller state (for each setup)
92
142
  start
93
143
  end
94
144
 
@@ -98,27 +148,132 @@ module Sbuilder
98
148
  # add loaders configured in 'sbuilder.yaml'
99
149
  factory.addLoaders( getConfiguredLoaders )
100
150
  end
101
-
102
- # @param possibilities [String:Array] possibilities defined in setup
103
- def start
104
- # init state
105
- @mappers = []
106
- @model = factory.createModel()
107
151
 
152
+ # @return [Hash] hash with keys for known extension-points, values []
153
+ private def initPartials
154
+ @logger.info "#{__method__}, starts"
155
+ return {
156
+ Sbuilder::Constants::EXTENSION_POINT_ASSUMPTIONS => [],
157
+ Sbuilder::Constants::EXTENSION_POINT_IMPLEMENTATION => [],
158
+ Sbuilder::Constants::EXTENSION_POINT_INVARIANT => [],
159
+ Sbuilder::Constants::EXTENSION_POINT_CONST => [],
160
+ Sbuilder::Constants::EXTENSION_POINT_MACRO => [],
161
+ Sbuilder::Constants::EXTENSION_POINT_OPERATIONS => [],
162
+ Sbuilder::Constants::EXTENSION_POINT_STATE => [],
163
+ }
108
164
  end
109
-
165
+
110
166
  # Iterate 'assumptions' and add to model assumption descritptions.
111
167
  # Issue a warning if assumptions not defined
112
168
  #
113
169
  # @param assumption [String:Array] name of assumption to activate
114
170
 
171
+
172
+ # Iterate 'snippets' array to load snippets to sbuilder code
173
+ # repository.
174
+ #
175
+ # @param [Array] snippets array of snippet loader definitions
176
+ #
177
+ def loadSnippets( snippets )
178
+
179
+
180
+ # access [Sbuilder::SnippetLoaderFacade]
181
+ snippetFacade = factory.getSnippetFacade( self )
182
+ snippetFacade.setMustache( factory.getSnippetFacadeMustache )
183
+
184
+ # add implementation snippets
185
+ loadInternalSnippets( snippetFacade )
186
+
187
+ snippets && snippets.each do |snippet|
188
+ loadSnippet( snippetFacade, snippet )
189
+ end
190
+
191
+ # once all snippets registered, facade manage singleton parser object
192
+ @logger.info "#{__method__} create new ParserFacade object"
193
+ parserFacade = factory.createParserFacade
194
+
195
+ snippetFacade.acceptSnippets( parserFacade.getResolver(self) )
196
+
197
+ end
198
+
199
+ # Add fixed platform snippets using 'loadSnippet' interface
200
+ #
201
+ # @param [Sbuilder::SnippetLoaderFacade] snippetFacade for snippet loader plugin
202
+ #
203
+ def loadInternalSnippets( snippetFacade )
204
+
205
+ root = File.join( File.dirname( __FILE__), "../../mustache/resources" )
206
+ internalSnippets = {
207
+ "className" => "Sbuilder::SnippetLoaderSimple",
208
+ "snippets" => [
209
+ {
210
+ 'metatype' => Sbuilder::Constants::META_MODEL_FRAMEWORK_SVC,
211
+ 'appName' => 'schedule_throw',
212
+ 'url' => File.join( root, "schedule_throw.tla" )
213
+ },
214
+ {
215
+ 'metatype' => Sbuilder::Constants::META_MODEL_FRAMEWORK_SVC,
216
+ 'appName' => 'schedule_process_mac',
217
+ 'url' => File.join( root, "schedule_process_macro.tla" )
218
+ },
219
+ {
220
+ 'metatype' => Sbuilder::Constants::META_MODEL_FRAMEWORK_SVC,
221
+ 'appName' => 'NewStep',
222
+ 'url' => File.join( root, "schedule_operator_new_step.tla" )
223
+ },
224
+ {
225
+ 'metatype' => Sbuilder::Constants::META_MODEL_FRAMEWORK_SVC,
226
+ 'appName' => 'schedule_process_proc',
227
+ 'url' => File.join( root, "schedule_process_procedure.tla" )
228
+ }
229
+ ]
230
+ }
231
+
232
+ loadSnippet( snippetFacade, internalSnippets )
233
+
234
+ end
115
235
 
116
- def loadAssumptions( assumptions )
236
+
237
+ # Load 'snippet' using object created for className
238
+ #
239
+ # @param [Sbuilder::SnippetLoaderFacade] snippetFacade for snippet
240
+ # loader plugin
241
+ #
242
+ #
243
+ # @param [Hash] snippet to load
244
+ # @option snippetLoader [String] metatype in specification code domain for the snippetBody
245
+ # @option snippetLoader [String] appName name of the snippet in application domain
246
+ # @option snippetLoader [String] file containing snippetBody to load
247
+ def loadSnippet( snippetFacade, snippet )
248
+
249
+ @logger.info "#{__method__}, snippet=#{snippet}"
250
+
251
+ Utils::Validate.validateProperties( snippet, Constants::VALIDATION[:snippet_loader_instantiate][:required], Constants::VALIDATION[:snippet_loader_instantiate][:allowed] )
252
+ Utils::Validate.oneOf( snippet, Constants::VALIDATION[:snippet_loader_instantiate][:one_of] )
253
+ # validateProperties( snippet, @@snippetLoaders_required, @@snippetLoaders_allowed )
254
+
255
+ # create new snippet loader instance ('className', 'configuration') OR access existing 'objectName'
256
+ loader = factory.getLoaderPlugin( snippet['className'], nil , snippet['objectName'] )
257
+ # configure facade
258
+ loader.setSnippetFacade( snippetFacade )
259
+ # configure new object (after facade set)
260
+ if snippet['className'] && snippet['configuration']
261
+ loader.configure( snippet['configuration'] )
262
+ end
263
+
264
+ # pass array of snippet definitions to plugin
265
+ begin
266
+ loader.registerSnippets( snippet['snippets'] )
267
+ rescue SbuilderException => e
268
+ msg = <<-EOS
269
+ #{e}
270
+
271
+ Error encountred, when loading snippet #{snippet.to_yaml}
272
+ EOS
273
+ @logger.error( "#{__method__}: #{msg}" )
274
+ raise ControllerException.new, msg, e.backtrace
275
+ end
117
276
 
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
277
  end
123
278
 
124
279
  # Iterate 'invariants' and add to model invariant descritptions.
@@ -157,7 +312,9 @@ module Sbuilder
157
312
 
158
313
  def loadResolvers( arrOfmappersTypePath )
159
314
  !arrOfmappersTypePath.nil? && arrOfmappersTypePath.each do |mapperDef|
160
- # add defaults to 'mapperDef'
315
+
316
+ # validate configuration
317
+
161
318
  mapperDef = defaultProps( mapperDef, @@resolverLoader_defaults )
162
319
  validateProperties( mapperDef, @@resolverLoader_required, @@resolverLoader_allowed )
163
320
  validateOne( mapperDef, @@resolverLoader_oneof )
@@ -166,9 +323,10 @@ module Sbuilder
166
323
  @logger.debug( "#{__method__} mapperDef=#{mapperDef} " )
167
324
 
168
325
  # find correct loader based on type
169
- loader = factory.getResolverLoader( getResolverDefType( mapperDef ) )
326
+ # loader = factory.getResolverLoader( getResolverDefType( mapperDef ) )
327
+ loader = getResolverLoader( getResolverDefType( mapperDef ) )
170
328
 
171
- # load an put array
329
+ # load an put array (calls mapperCreated)
172
330
  loaded = loader.load( getFileUrlOrPath( mapperDef ), self )
173
331
  # @mappers= mappers.concat(loaded) if loaded && loaded.any?
174
332
  @logger.info( "#{__method__} @mappers.length=#{@mappers.length}" )
@@ -182,43 +340,12 @@ module Sbuilder
182
340
  @mappers << mapper
183
341
  end
184
342
 
343
+ # @param name [String] resolver to find
344
+ # @return (first) resolver with 'name'
185
345
  def findResolver( name )
186
346
  @mappers.select{ |mapper| mapper.name == name }.first
187
347
  end
188
348
 
189
- # ------------------------------------------------------------------
190
- # load extensions
191
-
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 )
200
-
201
- # iteratio
202
- arrayOfExtensionDefs && arrayOfExtensionDefs.each do |extensionLoaderDef|
203
- validateProperties( extensionLoaderDef, @@extensionLoaderDef_required, @@extensionLoaderDef_allowed )
204
- validateOne( extensionLoaderDef, @@extensionLoaderDef_oneof )
205
- # ensure defaults in properties
206
- extensionLoaderDef = defaultProps( extensionLoaderDef, @@extensionLoaderDef_defaults )
207
-
208
-
209
- @logger.info( "#{__method__} extensionLoaderDef=#{extensionLoaderDef}" )
210
- loader = factory.getExtensionLoader( extensionLoaderDef['type'] )
211
- begin
212
- loader.load( getFileUrlOrPath( extensionLoaderDef ), self )
213
- rescue Exception => ee
214
- msg = "Error #{ee} caused by #{ee.backtrace.join("\n")} when loading '#{extensionLoaderDef['url']}'\n\n"
215
- @logger.error( "#{__method__} #{msg}" )
216
- raise ControllerException.new, msg, ee.backtrace
217
- end
218
- end
219
- # domainLoader = factory.get
220
- end
221
-
222
349
  # ------------------------------------------------------------------
223
350
  # load interfaces
224
351
 
@@ -227,10 +354,14 @@ module Sbuilder
227
354
  def loadInterfaces( arrOfparamsetTypePath )
228
355
  !arrOfparamsetTypePath.nil? && arrOfparamsetTypePath.each do |interfaceParamsetDef|
229
356
 
230
- begin
231
- validateProperties( interfaceParamsetDef, @@interfaceLoaderDef_required, @@interfaceLoaderDef_allowed )
232
- validateOne( interfaceParamsetDef, @@interfaceLoaderDef_oneof )
233
- validateOne( interfaceParamsetDef, @@interfaceLoaderDef_oneof2 )
357
+ begin
358
+ Utils::Validate.validateProperties( interfaceParamsetDef, Constants::VALIDATION[:api_loader_instantiate][:required], Constants::VALIDATION[:api_loader_instantiate][:allowed] )
359
+ Utils::Validate.oneOf( interfaceParamsetDef, Constants::VALIDATION[:api_loader_instantiate][:one_of_class_or_object] )
360
+ Utils::Validate.oneOf( interfaceParamsetDef, Constants::VALIDATION[:api_loader_instantiate][:one_of_file_or_url] )
361
+
362
+ # validateProperties( interfaceParamsetDef, @@interfaceLoaderDef_required, @@interfaceLoaderDef_allowed )
363
+ # validateOne( interfaceParamsetDef, @@interfaceLoaderDef_oneof )
364
+ # validateOne( interfaceParamsetDef, @@interfaceLoaderDef_oneof2 )
234
365
  rescue ControllerException => e
235
366
  msg = <<-EOS
236
367
  Error:
@@ -266,17 +397,19 @@ module Sbuilder
266
397
  className: Sbuilder::ParamSetLoaderSwagger
267
398
 
268
399
  EOS
269
-
270
- # find correct loader based on type & configure it
271
- loader = factory.getParamSetLoader( getParamsetType( interfaceParamsetDef ))
272
400
 
273
- # configure facade && pass it to loader
274
- facade = factory.getFacade(self)
275
- # facada loading instrcture services
401
+ # configure facade which get passed to loader
402
+ facade = factory.getApiFacade(self)
403
+ # generate support for returning 'response'
276
404
  facade.configureInfrastructureService( interfaceParamsetDef['infrastructureServices'] == true )
405
+ # generate interface process (allowing environment to call to the interface)
406
+ facade.configureInterfaceService( interfaceParamsetDef['interfaceServices'] == true ) if interfaceParamsetDef['interfaceServices']
277
407
  # facade creates definitions in 'namespace' (default nil = no group)
278
408
  facade.configureNamespace( interfaceParamsetDef['namespace'] )
279
409
  facade.setInterfaceCacheFilePath(getParamsetCacheFilePath(interfaceParamsetDef))
410
+
411
+ # find correct loader based on type & configure it
412
+ loader = factory.getLoaderPlugin( getParamsetType( interfaceParamsetDef ), interfaceParamsetDef['configuration'], interfaceParamsetDef['objectName'])
280
413
  loader.setFacade( facade )
281
414
 
282
415
  # load an put array
@@ -284,52 +417,321 @@ module Sbuilder
284
417
  # @paramSets = paramSets.concat( loaded ) if loaded && loaded.any?
285
418
  end
286
419
  end
420
+ # @!endgroup
287
421
 
288
- # # accept parameters set to model
289
- # def modelInterface( paramSet )
290
- # model.modelInterface( paramSet )
291
- # end
292
-
293
- # def paramSets
294
- # model.paramSets
295
- # end
296
422
 
297
423
  # ------------------------------------------------------------------
298
- # manages domains
424
+ # @!group processing steps
299
425
 
300
- # # called when loading mappers for each domain encountered, return domain
301
- # def domainEncountered( domainName )
302
- # model.domainEncountered( domainName )
303
- # end
426
+ # Reset @model, @mappers (=domain model resolvers)
427
+ # @param possibilities [String:Array] possibilities defined in setup
428
+ def start
429
+ # init state
430
+ @mappers = []
431
+ @model = factory.createModel()
304
432
 
305
- # # delegate to domains
306
- # def domains
307
- # model.domains
308
- # end
433
+ # no modifications for the setup
434
+ @updatedSetups = {}
435
+
436
+ # Clear caches
437
+ @extensionTemplates = nil
438
+
439
+ end
309
440
 
441
+ # load resolvers, interfaces, and invariants for application model
442
+ # (before setups are loaded).
310
443
 
311
- # load paremSets and mappers
444
+ # This means that symbol table cannot be initalized here (because
445
+ # it load implementation names, which are defines in setup
446
+ # extesion).
447
+ #
448
+ # @todo move implementation extension to model construct phase and
449
+ # initalize symbol table herre
312
450
  def load
313
451
  @logger.info( "#{__method__} load started" )
314
452
  loadResolvers( getResolversConfig )
315
453
  loadInterfaces( getInterfaceConfig )
316
454
  loadInvariants( getInvariantConfig )
455
+
456
+ # extract static partial calls in mustache templates into an array
457
+ resolveExtensionPartials
458
+
459
+ # create sbuilder (e.g. domain BOOLEAN) + application model
460
+ # extension (literals identified in application)
461
+
462
+ baseExtensionDefine
463
+
464
+ # create domain model i.e. resolve domains
465
+ resolve
466
+
467
+ # snippet may refer to symbol table -> init before snippet ldr
468
+ initializeSymbolTableMetaModel
469
+
470
+ # init symbol table with names in sbuilder & interface model
471
+ initializeSymbolTable
472
+
473
+ # snippet load extension point
474
+ loadSnippets( getSnippetConfig )
475
+
476
+ # topological sort
477
+ sortPartials
478
+
479
+ end
480
+
481
+ # Find domain for interface parameters, and for definitions (=types)
482
+ def resolve
483
+ resolveDomains
484
+ end
485
+
486
+ # Extract partial calls called in extension templates.
487
+ def resolveExtensionPartials
488
+ @logger.info "#{__method__} start"
489
+
490
+ # get Sbuilder::TemplateResolve used to access mustache
491
+ # templates
492
+ templateResolver = factory.getTemplateResolver( self )
493
+
494
+ # iterate extension templates in generate definition used to
495
+ # render 'tla/model.tla'
496
+
497
+ getExtensionTemplates.each do |extensionTemplate|
498
+ @logger.info( "#{__method__} extensionTemplate =#{extensionTemplate}" )
499
+ resolved_partials = templateResolver.resolve_partials( extensionTemplate )
500
+ # e.g. extend/extend_const.mustache --> 'const'
501
+ extensionPoint = extensionTemplate2Name(extensionTemplate)
502
+ # should use snippet-loader extension point
503
+ deprecated=true
504
+ addPartials( resolved_partials, extensionPoint, deprecated )
505
+ @logger.info( "#{__method__} extensionTemplate =#{extensionTemplate}--> resolved_partials=#{resolved_partials}" )
506
+ end
507
+
508
+ @logger.info "#{__method__} done"
509
+ end
510
+
511
+ # topological sort on partials
512
+ def sortPartials
513
+
514
+ # create object providing parser services
515
+ @logger.info "#{__method__} create new ParserFacade object"
516
+ parserFacade = factory.createParserFacade
517
+
518
+ # init
519
+ parserResolver = parserFacade.getResolver( self ) do |stat,entry,e|
520
+ # if error
521
+ if ( !stat )
522
+ end
523
+ end
524
+
525
+
526
+ partials.each do |partial_type, template_names|
527
+ @logger.debug "#{__method__} sort template_names=#{template_names} for partial_type #{partial_type}, " if @logger.debug?
528
+ partials[partial_type] = parserResolver.sortModules( template_names )
529
+ @logger.info "#{__method__} sorted template_names=#{partials[partial_type]} for partial_type #{partial_type}, "
530
+ end
531
+
532
+ end
533
+
534
+ # Create metamodel definitions in symbol table
535
+ def initializeSymbolTableMetaModel
536
+
537
+ @logger.info "#{__method__}, symbol table meta model inialization starts"
538
+
539
+ # Sbuilder::Constants::META_MODEL.each do |metatypeDef|
540
+ baseMetatypes.each do |metatypeDef|
541
+
542
+ @logger.info "#{__method__}, initiazlie symbol table metatypeDef=#{metatypeDef}"
543
+
544
+ # add metatype to symbol table
545
+ registerMetatype( metatypeDef )
546
+
547
+ end
548
+ end
549
+
550
+ # @return [Hash:Array] baseMetatype definitions
551
+ # @option baseMetatype [Symbol] :name
552
+ # @option baseMetatype [Symbol] :desc
553
+ def baseMetatypes
554
+ Sbuilder::Constants::META_MODEL
555
+ end
556
+
557
+ # Add metatype to symbol table
558
+ #
559
+ # @param [Hash] metatypeDef hash with metatype properties
560
+ def registerMetatype( metatypeDef )
561
+ symbolTable = getSymbolTable
562
+ symbolTable.defineMetaType( metatypeDef )
317
563
  end
564
+
318
565
 
566
+ # Add initial symbols to symbol table from generate definition
567
+ # producing module `tla/model.tla`
568
+ def initializeSymbolTable
569
+ @logger.info "#{__method__} start"
319
570
 
320
- # def extend
321
- # loadExtensions( getExtensionConfigs )
322
- # end
571
+ # Access (cached) symbol table for the specification model
572
+ symbolTable = getSymbolTable
573
+
574
+ # Generate definition used to render tla/model.tla
575
+ modeltemplate = getModelTemplate
576
+
577
+ # iterate inputs used to generate 'tla/model.tla', and
578
+ # locate entries defining 'symbols', and use the
579
+ # label to generate symbol table entries
580
+
581
+ # process all input definitions & consider only templates defining `modelData`
582
+ modeltemplate['inputs']. reject{ |i| i['modelData'].nil? }.each do |input|
583
+
584
+ # lamdba function to map element in modelData -array to symbol
585
+ # table definitions. Lamda on input definition takes
586
+ # precedence. Notice that input['symbols'] is actually a
587
+ # string which we have to convert to proc
588
+
589
+ next unless input['symbols']
590
+
591
+
592
+ # access model data, data array in
593
+ modelData = templateData( input['modelData'] )
594
+ d = modelData[input['modelData']]
595
+ @logger.debug "#{__method__} input['modelData']=#{input['modelData']}--> #{d}"
596
+ next unless d && d.any?
597
+
598
+ # allow one entry to define multiple symnbols
599
+ symbols = input['symbols'].is_a?( Array ) ? input['symbols'] : [ input['symbols']]
600
+
601
+ symbols.each do |symbol|
602
+
603
+ # it is a string, which needs to be evaluated to Proc
604
+ symbolsProc = eval symbol
605
+
606
+ # Add symbols to symbol table if 'symbols' lambda defined &&
607
+ # array modelData contains some symbols to add to symbol table
608
+ d.each_with_index do |element, index|
609
+
610
+ # Use lambda to map data model to symbol definition
611
+ symbolDefinition = symbolsProc.call( element )
612
+ # puts "symbolDefinition=#{symbolDefinition}"
613
+ @logger.debug "#{__method__} #{element} --> symbolDefinition #{symbolDefinition ? symbolDefinition.join(',') : 'nil' }"
614
+
615
+ # symbol definition is an array which can be unarrayd to define symbols, nil means no symbols found
616
+ symbolTable.addSymbol( *symbolDefinition ) unless symbolDefinition.nil?
617
+
618
+ end # iterata modelData
619
+ end # each - possible mutliple symbol defs
620
+
621
+ end
622
+ end
623
+
624
+ # Notify model for the setup being processed
625
+ #
626
+ # @param setupConf [Hash] setupConf
627
+ # @option setupConf [String] :setupDirectory name of the setup
628
+ # @option setupConf [String] :desc description
629
+ private def defineSetup( setupConf )
630
+ model.defineSetup( setupConf )
631
+ end
632
+
633
+ # Notify model for setup possibilities
634
+ private def setPossibilities( possibilities, setupName )
635
+ model.setPossibilities( possibilities )
636
+ end
637
+
638
+ # Load _setup_ assumptions to model
639
+ #
640
+ # @param assumptions [String:Array] name assumptions for a setup
641
+ # currently being processed
642
+ private def loadAssumptions( assumptions, setupName )
643
+
644
+ @logger.info "#{__method__}: assumptions=#{assumptions}"
645
+ assumptions.each do |assumption|
646
+ model.addAssumption( { :name => assumption, :desc => "Assume #{assumption}" } )
647
+ end # else - not nil
648
+ end
649
+
650
+ # Load setup specific extensions (e.g. possibilities, extend
651
+ # domains, extend implementation)
652
+ #
653
+ # @param setupName [String] name of setup, currently = extensionDirectory
654
+ # def loadExtensions( arrayOfExtensionDefs )
655
+ def loadExtensions( setupName )
656
+
657
+ # extension common for all setups
658
+ baseExtensionSetup
659
+
660
+ # access sbuilder.yaml configuration
661
+ arrayOfExtensionDefs = getSetupExtensions( setupName )
662
+
663
+ # iterate
664
+ arrayOfExtensionDefs && arrayOfExtensionDefs.each do |extensionLoaderDef|
665
+ validateProperties( extensionLoaderDef, @@extensionLoaderDef_required, @@extensionLoaderDef_allowed )
666
+ validateOne( extensionLoaderDef, @@extensionLoaderDef_oneof )
667
+ # ensure defaults in properties
668
+ extensionLoaderDef = defaultProps( extensionLoaderDef, @@extensionLoaderDef_defaults )
669
+
670
+
671
+ @logger.info( "#{__method__} extensionLoaderDef=#{extensionLoaderDef}" )
672
+ loader = factory.getExtensionLoader( extensionLoaderDef['type'], setupName )
673
+ begin
674
+ loader.load( getFileUrlOrPath( extensionLoaderDef ), self )
675
+ rescue Exception => ee
676
+ msg = "Error #{ee} caused by #{ee.backtrace.join("\n")} when loading '#{extensionLoaderDef['url']}'\n\n"
677
+ @logger.error( "#{__method__} #{msg}" )
678
+ raise ControllerException.new, msg, ee.backtrace
679
+ end
680
+ end
681
+ # domainLoader = factory.get
682
+ end
683
+
684
+ ##
685
+ # extend sbuilder domains, and application domains (literal
686
+ # values) before setup extensions are loader
687
+ #
688
+ #
689
+ # @see baseExtensionDefine for definition
690
+ def baseExtensionSetup
691
+
692
+ # literal in application
693
+ model.applicationDomainValues.each do |domainDef|
694
+ @logger.info "#{__method__}: application-domainDef=#{domainDef}"
695
+ dispatchExtendDomain( domainDef )
696
+ end
697
+
698
+ # defined in sbuilder - sbuilder knows these better than application
699
+ # howver setup may override
700
+ Constants::BASE_EXTENSIONS_DOMAIN.each do |domainDef|
701
+ @logger.info "#{__method__}: sbuilder-domainDef=#{domainDef}"
702
+ dispatchExtendDomain( domainDef )
703
+ end
704
+
705
+
706
+
707
+ end
708
+
709
+ ##
710
+ # define base/common domains for model
711
+ #
712
+ # @see baseExtensionSetup for extending domains
713
+ def baseExtensionDefine
714
+ Constants::BASE_EXTENSIONS_DOMAIN.each do |domainDef|
715
+ model.domainEncountered( domainDef['domain'] )
716
+ end
717
+
718
+ end
719
+
720
+ # @!endgroup
323
721
 
324
722
  # ------------------------------------------------------------------
325
- # iterate setups
326
723
 
724
+ # @!group Public services
725
+
726
+ # Process setup 'setupDirectory' or all setups (when 'setupDirectory' is nil)
727
+ #
728
+ # @param setupDirectory [String] name of setup to process
327
729
  def setup( setupDirectory=nil )
328
730
 
329
731
  @logger.info( "#{__method__} getSetups=#{getSetups.join( " ------------ " )}, #{getSetups.length}" )
330
732
  generated=false
331
733
 
332
- # deep down makes a new call to getSetups --> interation fails
734
+ # deep down makes a new call to getSetups --> iteration fails
333
735
  setups = Marshal.load( Marshal.dump( getSetups ))
334
736
  setups.each_with_index do |setupDef,i|
335
737
 
@@ -343,7 +745,7 @@ module Sbuilder
343
745
 
344
746
  output( 1, "------------------------------------------------------------------" ) if isOptFilterSrc
345
747
  output( 1, "generate setup: #{setupDef['setupDirectory']}" )
346
- generate( setupDef['setupDirectory'], setupDef['setupDirectory'] )
748
+ generateSetup( setupDef['setupDirectory'], setupDef['setupDirectory'] )
347
749
  @logger.info( "#{__method__} done to generate setupDirectory=#{setupDirectory} for #{setupDef}" )
348
750
  output( 2, "\n" )
349
751
 
@@ -351,6 +753,8 @@ module Sbuilder
351
753
 
352
754
  end
353
755
 
756
+ @logger.info "#{__method__} done iterating setups"
757
+
354
758
  raise ControllerException.new <<-EOS if !generated && setupDirectory
355
759
 
356
760
  Setup #{setupDirectory} not found - Nothing generated
@@ -359,9 +763,86 @@ module Sbuilder
359
763
 
360
764
  EOS
361
765
 
362
-
766
+ end
767
+
768
+ # @!endgroup
769
+
770
+ # ------------------------------------------------------------------
771
+ # @!group Used by resolveExtensionPartials
772
+
773
+ # Add 'resolved_partials' found in extensionTemplate to
774
+ # `extension_point( extensionTemplate )`
775
+ #
776
+ # @param extensionPoint [String] name of extension point
777
+ # (e.g. const, see src/extend/extend_*.tla)
778
+ #
779
+ # @return [Array] partials collected
780
+ #
781
+ # @option partials [String] key is extensionpoint corresponding
782
+ # 'extensionTemplate'
783
+ #
784
+ # @option partials [Array] value is array partials resolved in
785
+ # 'extensionTemplate' file
786
+ #
787
+ # @param [Boolean] depracted true when adding partials included using {{>partial}} syntax
788
+ #
789
+ def addPartials( resolved_partials, extensionPoint, deprecated=false )
790
+ raise "extensionPoint is nil" if extensionPoint.nil?
791
+ raise "@partials[extensionPoint] is nil" if @partials[extensionPoint].nil?
792
+ @logger.info( "#{__method__} extensionPoint=#{extensionPoint}:#{extensionPoint.class} added #{resolved_partials.join(',')}" )
793
+ @partials[extensionPoint] += resolved_partials
794
+ if deprecated
795
+ @logger.warn "Using DEPRACTED extension point '#{extensionPoint}' for partials: #{resolved_partials.join(', ')}"
796
+ @partials["DEPRECATED-#{extensionPoint}"] = resolved_partials
797
+ end
798
+ # @logger.debug "#{__method__} partials=#{partials}"
799
+ @partials
800
+ end
801
+
802
+ # Extract extension point name from 'extensionTemplate'
803
+ #
804
+ # @param extensionTemplate [String] e.g. extend/extend_const.mustache
805
+ #
806
+ # @return [String] extension point name extracted from extesion
807
+ # template name e.g. const
808
+ def extensionTemplate2Name( extensionTemplate )
809
+ name = extensionTemplate[/.*\/extend_([^.]+)/,1]
810
+ # @logger.debug "#{__method__}, name=#{name}:#{name.class}, extensionTemplate=#{extensionTemplate}:#{extensionTemplate.class}"
811
+ return name
812
+ end
813
+
814
+
815
+ # @return [Boolean] true if
816
+ def is_extension_point( template_name )
817
+ return template_name.match( /extend\/.*\.mustache/ )
363
818
  end
364
819
 
820
+
821
+
822
+ # Retrun list of template partials in extension points for
823
+ # +template_name+.
824
+ #
825
+ # @param [String] template_name to map extension point key
826
+ #
827
+ # @param [Boolean] depracted true when accessing partials included
828
+ # using {{>partial}} syntax, in this case return all depracted partials
829
+ #
830
+ # @return [String] partials for extension point
831
+ def getExtensionPointPartials( template_name, deprecated=false )
832
+
833
+ if ( deprecated ) then
834
+ ret = partials.keys.select { |k| k.start_with?( "DEPRECATED" )}.
835
+ map { |k| partials[k] }.flatten
836
+ @logger.warn "Returning DEPRACTED extension point partials: #{ret.join(', ')}"
837
+ return ret
838
+ end
839
+
840
+ extension_point = extensionTemplate2Name( template_name )
841
+ @logger.debug "#{__method__} lookup partials #{template_name}->#{extension_point} -> "
842
+ return partials[extension_point]
843
+ end
844
+
845
+ # @!endgroup
365
846
 
366
847
  # ------------------------------------------------------------------
367
848
  # resolve
@@ -374,9 +855,15 @@ module Sbuilder
374
855
  return nil
375
856
  end
376
857
 
858
+ ##
859
+ # Resolve domains (find domain name & domain object) for
860
+ # parameters sets in model. Only if resolve needed. Resolve also
861
+ # :response parameterSets (for interfaces).
862
+ #
377
863
  def resolveDomains
378
- @logger.info( "#{__method__} resolve started" )
379
- model.paramSets.each do |paramSet|
864
+ @logger.info( "#{__method__}: resolve started" )
865
+ # model.paramSets.each do |paramSet|
866
+ model.paramSets.select{|ps| ps.resolveNeeded( self ) }.each do |paramSet|
380
867
  # @logger.info( "#{__method__} paramSet id=#{paramSet.getId}" )
381
868
  resolver = findResolverForParameterSet( paramSet )
382
869
  if resolver.nil? then
@@ -399,25 +886,20 @@ module Sbuilder
399
886
  raise
400
887
  end
401
888
  end
402
-
403
889
  end
404
890
 
405
- def resolve
406
- resolveDomains
407
- end
408
891
 
409
- # ------------------------------------------------------------------
410
- # start, load, resolve, extend && output
892
+ # start, load, resolve, extend && render
411
893
  #
412
894
  # @param setupName [String] name of setup, currently = extensionDirectory
413
895
  # @param extensionDirectory [String] directory where setup generated
414
896
 
415
- def generate( setupName="default", extensionDirectory="default" )
897
+ def generateSetup( setupName="default", extensionDirectory="default" )
416
898
  @logger.info( "#{__method__} setupName=#{setupName}, extensionDirectory=#{extensionDirectory}" )
417
899
 
418
900
  processSetup( setupName ) do |name, setupConf, possibilities|
419
901
 
420
- # config && get renderes
902
+ # config && get renderer
421
903
  mustache = prepareRender( setupName )
422
904
 
423
905
  # path to directory where setup output is done
@@ -457,27 +939,33 @@ module Sbuilder
457
939
  # init state
458
940
  start
459
941
 
460
- # load configs
942
+ # load resolvers, interfaces, and invariants
461
943
  load
462
944
 
463
- # resolve domain
464
- resolve
945
+ # # create domain model i.e. resolve domains
946
+ # resolve
465
947
 
466
948
  # access config && put to model
467
949
  setupConf = getSetup( setupName )
468
950
  defineSetup( setupConf )
469
951
 
470
952
  # add assumptions to model
471
- loadAssumptions( getSetupAssumptionList( setupConf ) )
953
+ loadAssumptions( getSetupAssumptionList( setupConf ), setupName )
472
954
 
473
955
  # extensions
474
- loadExtensions( setupName )
956
+ loadExtensions( setupName )
957
+
958
+ # DEPREACTED # initializeSymbolTable called after extension load
959
+ # (but before generation) because 'interface-extension' sets
960
+ # META_MODEL_SERVICE_IMPLEMENTATION
961
+ # initializeSymbolTable
475
962
 
476
963
  # config model - before config rendering
477
964
  possibilities= getSetupPossibilitiesList( setupName )
478
- model.setPossibilities( possibilities )
965
+ setPossibilities( possibilities, setupName )
479
966
 
480
- yield setupName, setupConf, possibilities
967
+ # document or generate (possiblities)
968
+ yield setupName, setupConf, possibilities if blk
481
969
 
482
970
  end
483
971
 
@@ -497,14 +985,21 @@ module Sbuilder
497
985
 
498
986
  end
499
987
 
988
+ # Create a reader for accessing templates file, configure the
989
+ # reader, and create template renderer using that reader.
990
+ #
500
991
  # @return [Sbuilder::Template] mustache template generator
501
992
  def prepareRender( setupName )
502
993
 
503
- # access template generator from factory
994
+ # Known template readers:
995
+ # - TemplateReader: simple reader, return first file matching
996
+ # - TemplateContextReader: parsers template snippets, determine snippets reachable for
997
+ # setup steps, prune unreachable template snippets
998
+ #
504
999
  reader = factory.getTemplateReader( self )
505
1000
  # configure reader if it is ready to accept 'setupName'
506
1001
  reader.setSetupName( setupName ) if reader.respond_to?( :setSetupName )
507
- # pass reader to template generator
1002
+ # create pass reader to template generator
508
1003
  mustache = factory.getTemplate( reader )
509
1004
 
510
1005
  return mustache
@@ -519,7 +1014,7 @@ module Sbuilder
519
1014
  #
520
1015
  # @param generateCategory [Nil|String] choose templates in
521
1016
  # 'generateCategory', Nil = no category defined. Intended
522
- # usage for to generate possibitilies
1017
+ # usage for to generate possibitilies.
523
1018
  #
524
1019
  # @param mustache [Sbuilder::Template] generator to render
525
1020
  #
@@ -608,10 +1103,13 @@ module Sbuilder
608
1103
  # e.g. prune interfaces not used in setup
609
1104
  renderData = setupFilter( generateDef['modelData'], renderData )
610
1105
 
611
- # Iterate each 'template' in one 'generateDef' array (most often just one template)
612
- templates = generateDef['template'].is_a?( Array ) ? generateDef['template'] : [ generateDef['template'] ]
1106
+ # # Iterate each 'template' in one 'generateDef' array (most often just one template)
1107
+ # templates = generateDef['template'].is_a?( Array ) ? generateDef['template'] : [ generateDef['template'] ]
1108
+ template = getGenerateTemplate( generateDef )
1109
+ # @todo: remove array
1110
+ templates = [template]
613
1111
 
614
- # Support paramters to template
1112
+ # Support template paramaters
615
1113
  templateParameters = generateDef['templateParameters'].nil? ? {} : generateDef['templateParameters']
616
1114
 
617
1115
  # optional parameters added in generate -section
@@ -640,14 +1138,55 @@ module Sbuilder
640
1138
  :cat => lambda do |path_template|
641
1139
  path = mustache.render_str( path_template, renderData )
642
1140
  File.readlines( path.strip ).join('')
643
- end
1141
+ end,
1142
+ :dump_partials => lambda do |partial_type|
1143
+ partialNames = partials[partial_type] || []
1144
+ "#{partial_type} --> #{partialNames.join( ',' )}"
1145
+ end,
644
1146
  }
645
1147
 
1148
+ # specName <- SPEC_NAME( metatype, appName )
1149
+ renderData['SPEC_NAME'] = lambda do |type_appName|
1150
+ key = mustache.render_str( type_appName, renderData )
1151
+ keys = key.split( '.' )
1152
+ begin
1153
+ ret = getSymbolTable.lookupSymbol(keys[1], keys[0] )
1154
+ rescue Exception => ee
1155
+ msg =<<-EOS
1156
+ Error
1157
+
1158
+ #{ee}
1159
+ when accessing symbol table using key #{type_appName}
1160
+
1161
+ EOS
1162
+ @logger.error( "#{__method__} #{msg}" )
1163
+ raise ControllerException.new, msg, ee.backtrace
1164
+ end
1165
+ ret
1166
+ end
1167
+
1168
+
646
1169
  # support 'PREFERENCES'
647
- renderData.merge!( getPreferencesData(setupName ))
1170
+ renderData.merge!( getSetupPREFERENCES(setupName) )
648
1171
 
649
1172
  # finally render i.e. create string to output
650
- str = mustache.to_str( template, renderData )
1173
+ begin
1174
+ str = mustache.to_str( template, renderData )
1175
+ rescue Exception => ee
1176
+ msg =<<-EOS
1177
+ Error
1178
+
1179
+ #{ee}
1180
+
1181
+ when rendering template '#{template} using data
1182
+
1183
+ #{renderData.to_yaml}
1184
+
1185
+ EOS
1186
+ @logger.error( "#{__method__} #{msg}" )
1187
+ raise ControllerException.new, msg, ee.backtrace
1188
+ end
1189
+
651
1190
 
652
1191
  # output to file
653
1192
  @logger.info( "#{__method__} templateName=#{template}" )
@@ -700,9 +1239,10 @@ module Sbuilder
700
1239
  return ret
701
1240
  end
702
1241
 
703
- # Return names defined in mode (definitions)
1242
+ # Return names (e.g. definitions, domains) defined in the
1243
+ # specification model.
704
1244
  #
705
- # @return [String:Array] of names in define in model
1245
+ # @return [String:Array] of names in defined in model
706
1246
  def getModelNames
707
1247
  ret = []
708
1248
 
@@ -712,13 +1252,14 @@ module Sbuilder
712
1252
  # domain --> 'd_:domain_name'
713
1253
  ret += templateData( "domains" )['domains'].map { |d| "d_#{d[:domain_name]}"}
714
1254
 
715
- @logger.debug( "#{__method__} ret=#{ret.join(',')}" )
1255
+ @logger.debug( "#{__method__}: ret=#{ret.join(',')}" )
716
1256
  ret
717
1257
  end
718
1258
 
719
- # Return entry_points such that
720
- # interfaces[steps.interface_operation ==
721
- # intertafaces.interface_operation].implementation
1259
+ # Return 'implementation' and 'complation' for interfaces,
1260
+ # which are referenced on steps.
1261
+ #
1262
+ # Return also
722
1263
  #
723
1264
  # @return [String:Array] names of interface[:implementation]
724
1265
  #
@@ -732,7 +1273,10 @@ module Sbuilder
732
1273
  @logger.debug( "#{__method__}: setup_operations= #{setup_operations}" )
733
1274
  entry_points = interfaces.
734
1275
  select {|i| setup_operations[i[:interface_operation]] }.
735
- map { |i| i[:implementation] }
1276
+ map { |i| [ i[:implementation], i[:completion]] }.
1277
+ flatten.
1278
+ select {|e| e }
1279
+
736
1280
  @logger.info( "#{__method__}: entry_points= #{entry_points}" )
737
1281
  entry_points
738
1282
 
@@ -766,8 +1310,63 @@ module Sbuilder
766
1310
  model.assumptions.map{|a| a[:name] }
767
1311
  end
768
1312
 
769
- # ------------------------------------------------------------------
770
- # configuration
1313
+ # Add functions used in mustache rendering sections to 'renderData'
1314
+ #
1315
+ # @param [Hash] renderData to decorate
1316
+ #
1317
+ # @param [Mustache] mustache template tool to reander section text
1318
+ #
1319
+ # @return [Hash] renderData decorated with functions uses in
1320
+ # mustache rendering.
1321
+
1322
+ def decorateRenderData( renderData, mustache )
1323
+
1324
+ # META
1325
+ renderData['META'] =
1326
+ {
1327
+ :version => Sbuilder::version,
1328
+ :model_version => Sbuilder::model_version,
1329
+ :timestamp => Time.new.strftime( "%Y-%m-%d %H:%M:%S" ),
1330
+ # :desc => generateDef['desc'],
1331
+
1332
+ # :modelData => generateDef['modelData'],
1333
+ # :template => template,
1334
+ # :setup => setupName,
1335
+ # :outputDirectory => File.dirname( outputPath ),
1336
+ # :outputFile => File.basename( outputPath ),
1337
+ # :outputModule => File.basename( outputPath, ".*" ),
1338
+ }
1339
+
1340
+
1341
+
1342
+ renderData['SPEC_NAME'] = lambda do |type_appName|
1343
+ key = mustache.render( type_appName, renderData )
1344
+ keys = key.split( '.' )
1345
+ begin
1346
+ ret = getSymbolTable.lookupSymbol( keys[1], keys[0] )
1347
+ rescue Exception => ee
1348
+ msg =<<-EOS
1349
+ Error
1350
+
1351
+ #{ee}
1352
+
1353
+ Error encounterd, when accessing symbol table using key '#{type_appName}' in SPEC_NAME -lambda
1354
+
1355
+ EOS
1356
+ @logger.error( "#{__method__} #{msg}" )
1357
+ raise ControllerException.new, msg, ee.backtrace
1358
+ end
1359
+ ret
1360
+ end
1361
+
1362
+ renderData
1363
+
1364
+ end
1365
+
1366
+
1367
+
1368
+ # @!group Access sbuilder.yaml configuration
1369
+
771
1370
 
772
1371
 
773
1372
  # cache '@controller_config' read 'getConfigFilePath' and 'getInternalConfigFilePath', merge 'generate'
@@ -799,13 +1398,43 @@ module Sbuilder
799
1398
  getConfig()['setups']
800
1399
  end
801
1400
 
1401
+
1402
+ ##
1403
+ # For 'setupName' return configuration, which may be overridden
1404
+ # from setup extension loaders. (@see updateSetup)
1405
+ #
802
1406
  # @param setupName [String] name of setup to get
1407
+ #
803
1408
  # @return [Hash] hash of set in sbuilder configuration
804
1409
  def getSetup( setupName )
1410
+ (initialGetSetup( setupName ) || {} ).merge( updatedSetups[setupName] || {} )
1411
+ end
1412
+
1413
+
1414
+ ##
1415
+ # Return data for setup as configured in main-configuration file
1416
+ #
1417
+ # @param setupName [String] name of setup to get
1418
+ # @return [Hash] hash of set in sbuilder configuration
1419
+ def initialGetSetup( setupName )
805
1420
  setup = getSetups.select { |setup| setup['setupDirectory'] == setupName }.first
806
1421
  @logger.debug( "#{__method__} setupName=#{setupName}, setup=#{setup} " )
807
1422
  setup
808
1423
  end
1424
+
1425
+ ##
1426
+ # Update 'setupData' on 'setupName' configuration (possible done
1427
+ # in setup extension loaders).
1428
+ #
1429
+ # @param [String] setupName to update
1430
+ #
1431
+ # @param [Hash] setupData data to update on 'setupName'
1432
+ def updateSetup( setupName, setupData )
1433
+ @logger.info "#{__method__}: setupName=#{setupName} with data #{setupData}"
1434
+ @logger.debug "#{__method__}: data before update #{getSetup(setupName).to_yaml}" if @logger.debug?
1435
+ updatedSetups[setupName] = setupData
1436
+ @logger.debug "#{__method__}: data after update #{getSetup(setupName).to_yaml}" if @logger.debug?
1437
+ end
809
1438
 
810
1439
  # @return [Hash:Array] of 'type', 'url'|'file' properties
811
1440
  def getSetupExtensions( setupName )
@@ -827,18 +1456,36 @@ module Sbuilder
827
1456
 
828
1457
 
829
1458
 
830
- def getPreferencesData( setupName )
1459
+ # @return [Hash] renderData with PREFERENCES property
1460
+ private def getSetupPREFERENCES( setupName )
1461
+ getPreferencesDataHash( getMergedSetupPreferences( setupName ) )
1462
+ end
1463
+
1464
+ # Put 'prefs' into a hash in 'PREFERENCES' property
1465
+ private def getPreferencesDataHash( prefs )
831
1466
  renderData = {}
832
- renderData['PREFERENCES'] = getPreferencesWithDefaults( setupName )
1467
+ renderData['PREFERENCES'] = prefs
833
1468
  return renderData
834
1469
  end
1470
+
835
1471
 
836
- # Get prefecnces with default setttings
837
- # @return preferences [Hash] with values for all known preferences
838
- def getPreferencesWithDefaults( setupName )
839
- DEFAULT_PREFERENCES.merge( getPreferences ).merge( getSetupPrefences( setupName ))
1472
+ # @return [Hash] render data with 'PREFERENCES' -property with
1473
+ # default preferences, and common preference from sbuilder.yaml
1474
+ def getCommonPreferencesData
1475
+ getPreferencesDataHash( getCommonPreferences() )
840
1476
  end
841
1477
 
1478
+
1479
+ # Get preferences for default+common+setup
1480
+ private def getMergedSetupPreferences( setupName )
1481
+ getCommonPreferences.merge( getSetupPrefences( setupName ))
1482
+ end
1483
+
1484
+ # Get preferences for default+common
1485
+ def getCommonPreferences
1486
+ DEFAULT_PREFERENCES.merge( getPreferences )
1487
+ end
1488
+
842
1489
  # Access preferences in main configuration file 'sbuilder.yaml'
843
1490
  #
844
1491
  # @return preferences [Hash] possible empty (but definitely
@@ -859,6 +1506,86 @@ module Sbuilder
859
1506
  getOpt( :templates ).first
860
1507
  end
861
1508
 
1509
+ # Return cache directory location from opitions
1510
+ #
1511
+ # @return [String] path to cache -directory
1512
+ def getCacheDir
1513
+ getOpt(:cache_dir)
1514
+ end
1515
+
1516
+ # Return directory path for snippet directory, and ensure that the director exists
1517
+ #
1518
+ # @return [String] repositoryPath to root direcnoty under, which
1519
+ # to store snippets
1520
+ def snippetRepository
1521
+
1522
+ path = File.join( getOpt(:cache_dir), Sbuilder::Constants::SNIPPET_LOADER_DIR )
1523
+ Dir.mkdir( path ) unless File.exists?( path )
1524
+ path
1525
+
1526
+ end
1527
+
1528
+ # Return path to directory for 'metatype' in snippetRepository
1529
+ # (used by snippet loader), create the directory if it does not exists.
1530
+ #
1531
+ # @param [String] metatype in specification model
1532
+ #
1533
+ # @return [String] path to an existing snippet direcotory
1534
+
1535
+ def metatypeSnippetRepository( snippetRepository, metatype )
1536
+ path = File.join( snippetRepository, metatype )
1537
+ Dir.mkdir( path ) unless File.exists?( path )
1538
+ path
1539
+ end
1540
+
1541
+ # Return search array of directories/gem names from, which to
1542
+ # search templates to render.
1543
+ #
1544
+ # @return [String:Array] direcotorie (or gem names) to search for
1545
+ # render templates
1546
+ def templateRenderDirectories()
1547
+ options = @opts
1548
+ searchDirs = [ snippetRepository + "/" ] + options[:templates] + (options[:default_templates] || [] )
1549
+ @logger.info "#{__method__}, searchDirs=#{searchDirs.join(', ')}"
1550
+ searchDirs
1551
+ end
1552
+
1553
+
1554
+
1555
+
1556
+ # @!endgroup
1557
+
1558
+ # ------------------------------------------------------------------
1559
+ # @!group Access symbol table
1560
+
1561
+ def getMetaTypeDefinition( metatype )
1562
+ getSymbolTable.getMetaTypeDefinition( metatype )
1563
+ end
1564
+
1565
+ #
1566
+ # @!endgroup
1567
+
1568
+ # ------------------------------------------------------------------
1569
+ # @!group output
1570
+
1571
+
1572
+ def output( level, msg, nl=true )
1573
+ if nl
1574
+ puts msg if output_show( level )
1575
+ elsif output_show( level )
1576
+ print msg
1577
+ $stdout.flush
1578
+ end
1579
+ end
1580
+
1581
+ # @return [Boolean] true if output on level
1582
+ def output_show( level )
1583
+ level <= @opts[:verbosity]
1584
+ end
1585
+
1586
+ # @!endgroup
1587
+
1588
+
862
1589
  private
863
1590
 
864
1591
  # path to configuration file
@@ -876,12 +1603,17 @@ module Sbuilder
876
1603
  end
877
1604
 
878
1605
  def getExtensionConfigs
879
- getConfig()['extensions']
1606
+ ret = getConfig()['extensions']
1607
+ ret
880
1608
  end
881
1609
 
882
1610
  # @return [Hash] of extension properties
883
1611
  def getExtensions
884
- getConfig()['extend'] || {}
1612
+ ret = getConfig()['extend'] || {}
1613
+ @logger.debug "#{__method__}: extensions-to-return=#{ret}"
1614
+
1615
+ validateProperties( ret, @@extend_required, @@extend_allowed )
1616
+ ret
885
1617
  end
886
1618
 
887
1619
  # Api loaders configured in sbuilder.yaml['extend']['loaders']
@@ -889,8 +1621,10 @@ module Sbuilder
889
1621
  # @return [Hash:Array] with :name,:className,:configuration properties
890
1622
  def getConfiguredLoaders
891
1623
  loaders = getExtensions()['loaders'] || []
1624
+ @logger.debug "#{__method__}: loaders=#{loaders}"
892
1625
  loaders.each do |loader|
893
- validateProperties( loader, @@validExtendLoader )
1626
+ Utils::Validate.validateProperties( loader, Constants::VALIDATION[:extend_loader][:required], Constants::VALIDATION[:extend_loader][:allowed] )
1627
+ # validateProperties( loader, @@requireExtendLoader, @@allowExtendLoader )
894
1628
  end
895
1629
  loaders
896
1630
  end
@@ -905,12 +1639,22 @@ module Sbuilder
905
1639
  invariants = [invariants] if invariants.is_a?( Hash )
906
1640
  return invariants || []
907
1641
  end
908
-
1642
+
1643
+ # @return [Hash] snippetConfig from sbuilder.yaml['snippets']
1644
+ def getSnippetConfig
1645
+ getConfig()['snippets'] || {}
1646
+ end
1647
+
909
1648
 
910
1649
  # @param generateCategory [Nil|String] choose templates in
911
- # 'generateCategory', @return [Hash:Array] of {'output', 'inputs'}
912
- # defining a file to render using templates in 'inputs'
913
- def getGenerateConfig( generateCategory )
1650
+ # 'generateCategory', nil for all templates
1651
+ #
1652
+ # @param output [Nil|String] or choose template where 'output' property mathces
1653
+ #
1654
+ #
1655
+ # @return [Hash:Array] of {'output', 'inputs'} defining a file to
1656
+ # render using templates in 'inputs'
1657
+ def getGenerateConfig( generateCategory, output=nil )
914
1658
  ret = getConfig()['generate']
915
1659
  if ret.nil? then
916
1660
  warn <<-EOS
@@ -923,9 +1667,47 @@ module Sbuilder
923
1667
  end
924
1668
 
925
1669
  # Screen category
926
- ret.select { |c| c['category'] == generateCategory }
1670
+ ret.select { |c| (c['category'] == generateCategory && output.nil?) || (c['output'] == output && generateCategory.nil? ) }
1671
+ end
1672
+
1673
+ # @return [Hash] generateConfig defining model.tla module
1674
+ # @option generateConfig [String] inputs array of input mustache templates
1675
+ def getModelTemplate
1676
+ modeltemplate = getGenerateConfig( nil, Sbuilder::Constants::MODEL_TEMPLATE_OUTPUT ).first
1677
+ end
1678
+
1679
+
1680
+ # Extract extension templates from generate configuration, cache
1681
+ # templates in @extensionTemplates
1682
+ #
1683
+ #
1684
+ # @return [String:Array] extension template names ie. names with matching 'extend/*.mustache'
1685
+ def getExtensionTemplates
1686
+ return @extensionTemplates if @extensionTemplates
1687
+
1688
+ # access generate configuration defining 'model.tla'
1689
+ # modeltemplate = getGenerateConfig( nil, Sbuilder::Constants::MODEL_TEMPLATE_OUTPUT ).first
1690
+ modeltemplate = getModelTemplate
1691
+
1692
+ @extensionTemplates = modeltemplate && modeltemplate ['inputs' ] && modeltemplate['inputs'].
1693
+ select { |i| is_extension_point( i['template'] ) }.
1694
+ map {|i| i['template']} || []
1695
+
1696
+ @logger.info "#{__method__} extensionTemplates=#{@extensionTemplates}"
1697
+ return @extensionTemplates
1698
+ end
1699
+
1700
+ # Return name of template to use in generation
1701
+ #
1702
+ # @param generateDef [Hash] generate definition
1703
+ # @option generateDef [String] 'template' name of template to generate
1704
+
1705
+ private def getGenerateTemplate( generateDef )
1706
+ # default uses template name
1707
+ return generateDef['template']
927
1708
  end
928
1709
 
1710
+
929
1711
  # return uri whero load from
930
1712
  def getFileUrlOrPath( paramSetDef )
931
1713
  @logger.info( "#{__method__} paramSetDef=#{paramSetDef}" )
@@ -941,8 +1723,8 @@ module Sbuilder
941
1723
 
942
1724
  # @return [String] path to cacheFilePath, if no 'cache' -property
943
1725
  def getParamsetCacheFilePath( paramSetDef )
944
- return "#{getOpt(:cache_dir)}/#{paramSetDef['cache']}" if paramSetDef['cache'] && getOpt(:cache_dir)
945
- return paramSetDef['cache'] if paramSetDef['cache']
1726
+ return "#{getCacheDir}/#{paramSetDef['cache']}" if paramSetDef['cache'] # && getOpt(:cache_dir)
1727
+ # return paramSetDef['cache'] if paramSetDef['cache']
946
1728
  return nil
947
1729
  end
948
1730
 
@@ -980,22 +1762,13 @@ module Sbuilder
980
1762
  getOpt( :filter_src )
981
1763
  end
982
1764
 
983
- # ------------------------------------------------------------------
984
- # output
1765
+ # @!endgroup
1766
+ # Configuration
985
1767
 
986
- def output( level, msg, nl=true )
987
- if nl
988
- puts msg if output_show( level )
989
- elsif output_show( level )
990
- print msg
991
- $stdout.flush
992
- end
993
- end
1768
+ # Configuration
994
1769
 
995
- # @return [Boolean] true if output on level
996
- def output_show( level )
997
- level <= @opts[:verbosity]
998
- end
1770
+ # @!group helpers
1771
+
999
1772
 
1000
1773
  # validate 'defintionHash' all 'required'/only 'allowed' props set
1001
1774
  private def validateProperties( defintionHash, required, allowed=nil )
@@ -1021,7 +1794,8 @@ module Sbuilder
1021
1794
  end
1022
1795
  end
1023
1796
 
1024
-
1797
+
1798
+ # @!endgroup
1025
1799
 
1026
1800
  end # class
1027
1801