tla-sbuilder 0.2.2 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (127) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +150 -116
  3. data/VERSION +1 -1
  4. data/lib/cli/cli-customer.rb +23 -3
  5. data/lib/cli/cli-pet.rb +66 -12
  6. data/lib/cli/cli-text.rb +127 -8
  7. data/lib/cli/cli.rb +49 -6
  8. data/lib/sbuilder.rb +26 -3
  9. data/lib/sbuilder/constants.rb +165 -6
  10. data/lib/sbuilder/controller.rb +943 -169
  11. data/lib/sbuilder/controller_utils.rb +122 -0
  12. data/lib/sbuilder/default-sbuilder.yaml +38 -44
  13. data/lib/sbuilder/domain.rb +160 -36
  14. data/lib/sbuilder/domain_cardinality.rb +1 -1
  15. data/lib/sbuilder/domain_range.rb +102 -0
  16. data/lib/sbuilder/domain_type.rb +150 -0
  17. data/lib/sbuilder/domain_value.rb +21 -13
  18. data/lib/sbuilder/exception.rb +16 -0
  19. data/lib/sbuilder/extension_loader.rb +67 -686
  20. data/lib/sbuilder/extension_loader_deprecated_step_extensions.rb +711 -0
  21. data/lib/sbuilder/extension_loader_step_generator.rb +876 -0
  22. data/lib/sbuilder/facade/{api_loader.rb → api_loader_facade.rb} +176 -45
  23. data/lib/sbuilder/facade/api_loader_plugin.rb +6 -32
  24. data/lib/sbuilder/facade/api_loader_plugin_mixer.rb +35 -0
  25. data/lib/sbuilder/facade/facade_constants.rb +23 -0
  26. data/lib/sbuilder/facade/loader_plugin_root.rb +56 -0
  27. data/lib/sbuilder/facade/param_set_root.rb +55 -0
  28. data/lib/sbuilder/facade/snippet_loader_facade.rb +600 -0
  29. data/lib/sbuilder/facade/snippet_loader_plugin.rb +76 -0
  30. data/lib/sbuilder/facade/snippet_loader_plugin_mixer.rb +56 -0
  31. data/lib/sbuilder/factory.rb +224 -45
  32. data/lib/sbuilder/model.rb +125 -45
  33. data/lib/sbuilder/mustache/template.rb +107 -58
  34. data/lib/sbuilder/mustache/template_reader.rb +56 -46
  35. data/lib/sbuilder/mustache/template_reader_context.rb +64 -234
  36. data/lib/sbuilder/mustache/template_resolve.rb +103 -0
  37. data/lib/sbuilder/mustache/template_root.rb +71 -0
  38. data/lib/sbuilder/param_set.rb +30 -15
  39. data/lib/sbuilder/param_set_db.rb +1 -1
  40. data/lib/sbuilder/param_set_def.rb +6 -1
  41. data/lib/sbuilder/param_set_def_func.rb +39 -0
  42. data/lib/sbuilder/param_set_if.rb +45 -10
  43. data/lib/sbuilder/param_set_loader_swagger.rb +56 -26
  44. data/lib/sbuilder/param_set_step.rb +1 -1
  45. data/lib/sbuilder/param_sets.rb +2 -1
  46. data/lib/sbuilder/parameter.rb +9 -3
  47. data/lib/sbuilder/parameter_container.rb +1 -1
  48. data/lib/sbuilder/parameter_dom.rb +17 -5
  49. data/lib/sbuilder/parameter_ref.rb +39 -10
  50. data/lib/sbuilder/parser/parser_facade.rb +310 -0
  51. data/lib/sbuilder/resolver.rb +11 -6
  52. data/lib/sbuilder/resolver_loader.rb +1 -1
  53. data/lib/sbuilder/resolver_loader_yaml.rb +1 -1
  54. data/lib/sbuilder/resolver_rule.rb +1 -1
  55. data/lib/sbuilder/resolver_rule_match.rb +10 -4
  56. data/lib/sbuilder/resolver_rule_ref.rb +1 -1
  57. data/lib/sbuilder/setup_loader.rb +49 -0
  58. data/lib/sbuilder/setup_loader_env.rb +478 -0
  59. data/lib/sbuilder/setup_loader_pref.rb +56 -0
  60. data/lib/sbuilder/snippet_loader_simple.rb +125 -0
  61. data/lib/sbuilder/spec/api_loader.rb +34 -0
  62. data/lib/sbuilder/spec/api_loader_facade.rb +169 -32
  63. data/lib/sbuilder/spec/loader_plugin.rb +98 -0
  64. data/lib/sbuilder/spec/snippet_loader.rb +228 -0
  65. data/lib/sbuilder/symbol_table.rb +279 -0
  66. data/lib/utils/{cache_lines.rb → fileio.rb} +8 -1
  67. data/lib/utils/logger.rb +2 -1
  68. data/lib/utils/powerset.rb +13 -0
  69. data/lib/utils/validate.rb +38 -0
  70. data/mustache/cfg/const_def.mustache +2 -0
  71. data/mustache/cfg/macro_run.mustache +1 -4
  72. data/mustache/data-model-header.mustache +1 -0
  73. data/mustache/definition_types.mustache +34 -4
  74. data/mustache/domains.mustache +1 -1
  75. data/mustache/domains_assign.mustache +1 -1
  76. data/mustache/infrastructure-service-init.mustache +1 -1
  77. data/mustache/interface_processes.mustache +16 -10
  78. data/mustache/interface_types.mustache +37 -11
  79. data/mustache/operator-infrastructure-service.mustache +1 -1
  80. data/mustache/resources/schedule_operator_new_step.tla +8 -0
  81. data/mustache/resources/schedule_process_macro.tla +37 -0
  82. data/mustache/resources/schedule_process_procedure.tla +22 -0
  83. data/mustache/resources/schedule_throw.tla +16 -0
  84. data/mustache/setup/domains_run.mustache +8 -2
  85. data/mustache/setup/operator_run.mustache +0 -4
  86. data/mustache/setup/steps_run.mustache +4 -3
  87. data/mustache/setup/steps_run_parameterBind.mustache +14 -6
  88. data/mustache/setup/steps_run_parameterExact.mustache +7 -3
  89. data/mustache/state_type_invariant-infrastructure-service.mustache +9 -4
  90. data/mustache/tla/const_def.mustache +1 -1
  91. data/mustache/tla/macro_run.mustache +7 -1
  92. data/mustache/tla/module_header.mustache +1 -1
  93. data/mustache/tla/operator_run.mustache +8 -5
  94. data/mustache/tla/plc_define_run.mustache +45 -36
  95. data/mustache/tla/plc_run_state.mustache +12 -5
  96. data/src-extend/extend/extend_assumptions.mustache +3 -0
  97. data/src-extend/extend/extend_const.mustache +3 -0
  98. data/src-extend/extend/extend_implementation.mustache +3 -0
  99. data/src-extend/extend/extend_invariant.mustache +3 -0
  100. data/src-extend/extend/extend_macros.mustache +3 -0
  101. data/src-extend/extend/extend_operations.mustache +3 -0
  102. data/src-extend/extend/extend_state.mustache +3 -0
  103. data/src/pet/extend/extend_assumptions.mustache +4 -0
  104. data/src/pet/extend/extend_implementation.mustache +3 -0
  105. data/src/pet/extend/extend_invariant.mustache +3 -0
  106. data/src/pet/extend/extend_macros.mustache +3 -0
  107. data/src/pet/extend/extend_operations.mustache +4 -0
  108. data/src/pet/extend/extend_state.mustache +3 -0
  109. data/src/pet/interface +5 -5
  110. data/src/pet/interface_delete_pet.tla +1 -1
  111. data/src/pet/interface_get_pet.tla +1 -1
  112. data/src/pet/interface_post_pet.tla +4 -2
  113. data/src/pet/interface_post_tag.tla +1 -1
  114. data/src/pet/interface_put_tag.tla +1 -1
  115. data/tla-sbuilder.gemspec +3 -3
  116. metadata +44 -19
  117. data/mustache/name_definition_type.mustache +0 -5
  118. data/mustache/name_domain.mustache +0 -5
  119. data/mustache/name_domain_value.mustache +0 -5
  120. data/mustache/name_domain_value_prefix.mustache +0 -5
  121. data/mustache/name_interface_response_type.mustache +0 -6
  122. data/mustache/name_interface_type.mustache +0 -6
  123. data/mustache/name_parameter_type.mustache +0 -6
  124. data/mustache/name_process.mustache +0 -6
  125. data/mustache/state_type_invariant.mustache +0 -17
  126. data/mustache/state_variables.mustache +0 -20
  127. data/src-extend/extend/extend_invariant_cfg.mustache +0 -7
@@ -0,0 +1,23 @@
1
+ module Sbuilder
2
+
3
+ module FacadeConstants
4
+
5
+ # Meta model keys
6
+ META_MODEL_DOMAINS="domains"
7
+ META_MODEL_DEFINITIONS="definitions"
8
+ META_MODEL_INTERFACE_TYPES="interface_types"
9
+ META_MODEL_INTERFACE_RESPONSE_TYPES="interface_response_types"
10
+ META_MODEL_PROCESSES="processes"
11
+ META_MODEL_SERVICE_IMPLEMENTATION="service_implementation"
12
+ META_MODEL_SERVICE_COMPLETION="service_completion"
13
+ META_MODEL_INFRA_SERVICES="infra_services"
14
+ META_MODEL_FRAMEWORK_SVC="framework-svc"
15
+ META_MODEL_INVARIANT='invariants'
16
+
17
+ end
18
+
19
+ class Facade
20
+ include Sbuilder::FacadeConstants
21
+ end
22
+
23
+ end
@@ -0,0 +1,56 @@
1
+ module Sbuilder
2
+
3
+ # Abstract base class for loader plugins
4
+ #
5
+ # Known child classes: ApiLoaderPlugin, SnippetLoaderPlugin
6
+
7
+ class LoaderPluginRoot
8
+
9
+ PROGNAME = nil # progname for logger default class name
10
+ include Sbuilder::Utils::MyLogger # mix logger
11
+
12
+ def initialize( options = {} )
13
+
14
+ @logger = getLogger( PROGNAME, options )
15
+ @logger.info( "#{__method__} initialized, options=#{options}" )
16
+
17
+
18
+ end
19
+
20
+
21
+ # #configure method called by controller
22
+ #
23
+ # @return [LoaderPluginRoot] self
24
+ #
25
+ def configure( configuration )
26
+ doConfigure( configuration )
27
+ self
28
+ end
29
+
30
+ # base class should implement 'doConfigure'
31
+ def doConfigure( configuration )
32
+ warn "Pluging '#{self.class.to_s}' should implement doConfigure"
33
+ end
34
+
35
+ # @return [Logger] log to Sbuiler log-file
36
+ def logger
37
+ @logger
38
+ end
39
+
40
+ def self.validateProperties( hash, required_props, allowed_props )
41
+ Sbuilder::Utils::Validate.validateProperties( hash, required_props, allowed_props )
42
+ end
43
+
44
+
45
+ def validateProperties( hash, required_props, allowed_props )
46
+ self.class.validateProperties( hash, required_props, allowed_props )
47
+ end
48
+
49
+ def oneOf( defintionHash, propList, min=1, max=1 )
50
+ Sbuilder::Utils::Validate.oneOf( defintionHash, propList, min, max )
51
+ end
52
+
53
+
54
+ end
55
+
56
+ end
@@ -0,0 +1,55 @@
1
+ module Sbuilder
2
+
3
+ # Abstract base class for parameter sets (definitions,
4
+ # interfaces). Provides common method to add parameters to the
5
+ # parameter set.
6
+ #
7
+ # @attr parameters [Sbuilder:Parameter::Array] array of parameters
8
+ #
9
+
10
+ class ParamSetRoot
11
+
12
+
13
+ attr_reader :parameters # array of parameters:Parameter
14
+
15
+ # ------------------------------------------------------------------
16
+ # @!group Constructor and Object Initialize
17
+
18
+
19
+ # constructor for the abstact class
20
+ def initialize( options = {} )
21
+ @parameters = []
22
+ end
23
+
24
+ # @!endgroup
25
+
26
+ # ------------------------------------------------------------------
27
+ # @!group Configure Model Object Relationships
28
+
29
+ # Add a 'parameter' to known parameters in the parameter set.
30
+ #
31
+ # @param param[Sbuilder::parameter] parameter to add
32
+ def addParameter( param )
33
+ parameters << param
34
+ self
35
+ end
36
+
37
+ # @param [String] name to look
38
+ #
39
+ # @return [Sbuilder::Parameter|nil] return parameter with name, nil if not found
40
+ def lookupParameter( name )
41
+
42
+ parameters.each do |parameter|
43
+ return parameter if parameter.name == name
44
+ end
45
+
46
+ # not found
47
+ return nil
48
+
49
+ end
50
+
51
+ # @!endgroup
52
+
53
+
54
+ end # class
55
+ end
@@ -0,0 +1,600 @@
1
+ module Sbuilder
2
+
3
+ # Facade providing interface to concrete 'SnippetLoaderPlugin'
4
+ # -classes.
5
+ #
6
+ #
7
+ # Facade operator (and snippet plugin) implement choreography:
8
+ #
9
+ # * expect 'metatype' to be registered: either it is sbuilder
10
+ # * defined metatype, it has been registered previously, or
11
+ # * plugin has registered 'metatype' using #registerMetatype -api
12
+ # * provided by facade.
13
+ #
14
+ # * hand over: snippet plugin passess snippet `metatype`, `appName`,
15
+ # `snippetBody` to facade
16
+ #
17
+ # * generate specName: facade generates `specName` = for `metatype`,
18
+ # `appName` pair
19
+ #
20
+ # * register snippet matadata to symbol table: facade passes snippet matadata
21
+ # `metatype`, `appName`, `specName` to symbol table in controller
22
+ #
23
+ # * render snippet code: facade render `snippetBody` to create
24
+ # `snippetCode`. Rendering resolves references in `snippetBody`
25
+ # from application namespace to specification namespace allowing
26
+ # snippet plugins to be unaware of names used in specification
27
+ # code. Rendering (=preferred mode of operation) may also resolve
28
+ # `snippetName` if `snippetBody` is given using template reference,
29
+ # instead of fixed name.
30
+ #
31
+ # * parse snippet code: facade access parser (via ParserFacade), and
32
+ # parses `snippetCode`.
33
+ #
34
+ # * check snippet name: facade ensures that `snitppetName` matches
35
+ # `specName`
36
+ #
37
+ # * service implementation: `metatype` == META_MODEL_SERVICE_IMPLEMENTATION
38
+ # registers `specName` as
39
+ #
40
+ # * save snippet: snippet is saved in Sbuilder `codeRepository` into
41
+ # `metatype` specific directory using a file referring to `appName`.
42
+ #
43
+ # * add snippet to generation/render phases:
44
+ #
45
+ #
46
+ # Error modes:
47
+ #
48
+ # - unknown `metatype`: raise exception (and quit processing is
49
+ # allowed because this indicates a problem in general setup
50
+ #
51
+ # - `specName` and `snippetName` mismatch: may result if snippet
52
+ # loader defines `spectName`, or if `snippetBlock` does no
53
+ # correctly render `snippetName`
54
+ #
55
+ # - snippet metadata uniqueness: `specName` is unique, also
56
+ # `metatype`/`appName` combination
57
+ #
58
+ # - unnkwon reference: render -problem, e.g. SPEC_NAME not found
59
+ #
60
+ #
61
+ # The use case is implemented using two public api inferfaces:
62
+ #
63
+ # * handOver: api being called by snippet loader
64
+ #
65
+ # * acceptSnippets: api being called by controller (once all
66
+ # snippets have been handed over)
67
+
68
+ # @attr_reader [Hash:Array] snippets handed over to facade
69
+ # @option snippets [String] metatype
70
+ # @option snippets [String] appName
71
+ # @option snippets [String] snippetBody
72
+ #
73
+ #
74
+ # @attr_reader [Sbuilder::Controller] controller running sbuilder
75
+
76
+
77
+
78
+ class SnippetLoaderFacade
79
+
80
+ extend Forwardable # for easy delegation
81
+
82
+ # [Hash:Array] of snippets handed over to facade
83
+ attr_reader :snippets
84
+
85
+ # [Sbuilder:Controller]
86
+ attr_reader :controller
87
+
88
+ # @attr [String] snippetHeader prefix to wrap snippetBody
89
+ attr_reader :snippetHeader
90
+
91
+ # @atr [String] postfix to wrap snippetBody
92
+ attr_reader :snippetFooter
93
+
94
+
95
+ # ------------------------------------------------------------------
96
+
97
+ # progname for logger
98
+ PROGNAME = nil # progname for logger default class name
99
+ include Sbuilder::Utils::MyLogger # mix logger
100
+
101
+ # Map parser node_type to extension point name
102
+ @@snippetType2extensionPointMapper = {
103
+ 'Macro' => Sbuilder::Constants::EXTENSION_POINT_MACRO,
104
+ 'Procedure' => Sbuilder::Constants::EXTENSION_POINT_IMPLEMENTATION,
105
+ 'VariableDef' => Sbuilder::Constants::EXTENSION_POINT_STATE,
106
+ 'OperatorDef' => Sbuilder::Constants::EXTENSION_POINT_OPERATIONS,
107
+ }
108
+
109
+ DEFAULT_SNIPPET_HEADER = <<-EOS.unindent
110
+ (* SNIPPET: {{metatype}}/{{appName}} --> {{specName}} *)
111
+ EOS
112
+
113
+ DEFAULT_SNIPPET_FOOTER = <<-EOS.unindent
114
+ (* --END OF SNIPPET-- *)
115
+
116
+ EOS
117
+
118
+
119
+ # ------------------------------------------------------------------
120
+ # @!group Construtor
121
+
122
+ def initialize( factory, options = {} )
123
+
124
+ @logger = getLogger( PROGNAME, options )
125
+ @logger.info( "#{__method__} initialized" )
126
+
127
+ # collaborators init
128
+ setFactory( factory )
129
+ @controller = nil
130
+
131
+ # snippets handed over to facade
132
+ @snippets = []
133
+
134
+ @options = options
135
+
136
+ @snippetHeader = DEFAULT_SNIPPET_HEADER
137
+ @snippetFooter = DEFAULT_SNIPPET_FOOTER
138
+
139
+ end
140
+
141
+ # @!endgroup
142
+
143
+ # ------------------------------------------------------------------
144
+ # @!group Prepare Facade
145
+
146
+ # Allow facade to access controller services
147
+ # @param controller [Sbuilder::Controller] controller sets self
148
+ def setController( controller )
149
+ @controller = controller
150
+ end
151
+
152
+ # Facade delagates the task to create new objects to `factory
153
+ # @param factory [Sbuilder::Factory] to create new obejcts
154
+ def setFactory( factory )
155
+ @factory = factory
156
+ end
157
+
158
+ def setMustache( mustache )
159
+ @mustache = mustache
160
+ end
161
+
162
+ ##
163
+ # Set 'snippetHeader' to wrap around snippets
164
+ def setSnippetHeader( snippetHeader )
165
+ @snippetHeader = snippetHeader
166
+ end
167
+
168
+ # Set 'snippetFooter' to wrap around snippets
169
+ def setSnippetFooter( snippetFooter )
170
+ @snippetFooter = snippetFooter
171
+ end
172
+
173
+ # @!endgroup
174
+
175
+ # ------------------------------------------------------------------
176
+ # @!group SnippetLoaderPlugin defines metatype
177
+
178
+ ##
179
+ # Return array of base metatypes in sbuilder context
180
+ #
181
+ # @return [Hash] baseMetatypes
182
+ # @option baseMetatype [Symbol] :name of metatype
183
+ # @option baseMetatype [Symbol] :desc metatype description
184
+ def baseMetatypes
185
+ controller.baseMetatypes
186
+ end
187
+
188
+
189
+ ##
190
+ # Add 'metatype' with 'desc' and optional 'prefix' to sbuilder
191
+ # context.
192
+ def registerMetatype( metatype, desc, prefix=nil )
193
+ @logger.info "#{__method__}, metatype='#{metatype}', desc=#{desc}"
194
+ metatypeDef = createMetatypeDef( metatype, desc, prefix )
195
+ controller.registerMetatype( metatypeDef )
196
+ end
197
+
198
+ private def createMetatypeDef( metatype, desc, prefix )
199
+ {
200
+ :name => metatype,
201
+ :desc => desc,
202
+ :prefix => prefix,
203
+ }
204
+ end
205
+
206
+ # ------------------------------------------------------------------
207
+ # @!group SnippetLoaderPlugin hands over snippet
208
+
209
+
210
+ # snippet plugin passess snippet `metatype`, `appName`,
211
+ # `specName`=nil, and `snippetBody` to facade.
212
+ #
213
+ # @param [String] metatype in specification model
214
+ #
215
+ # @param [String] appName in application domain being modeled in
216
+ # `snippetBody`, identified by `metatype`, `appName`, or
217
+ # `specName.`
218
+ #
219
+ # @param [String] specName used to identify `snippetBody` ,
220
+ # default nil allows sbuilder to generate `specName`. Nil no body
221
+ #
222
+ # @param [String] specName use as specName
223
+
224
+
225
+ def handOver( metatype, appName, snippetBody=nil, specName=nil )
226
+ # collect snippets handed over
227
+ @logger.info "#{__method__}, metatype=#{metatype}, appName=#{appName}, snippetBody=#{snippetBody}"
228
+
229
+ # generate specName & combine to hash
230
+ entry = snippetEntry( metatype, appName, snippetBody )
231
+
232
+ # override default specName
233
+ entry['specName'] = specName unless specName.nil?
234
+
235
+ # enable mapping from 'metatype/appName' to 'specName'
236
+ addSymbol( metatype, appName, entry['specName'] )
237
+
238
+ # TLA code generated for interface defition need to entry point
239
+ # to model implementation defined using
240
+ # META_MODEL_SERVICE_IMPLEMENTATION -metatype
241
+ if ( metatype == Sbuilder::Constants::META_MODEL_SERVICE_IMPLEMENTATION ) then
242
+ interfaceExtension( appName, entry['specName'], 'implementation' )
243
+ elsif metatype == Sbuilder::Constants::META_MODEL_SERVICE_COMPLETION
244
+ interfaceExtension( appName, entry['specName'], 'completion' )
245
+ end
246
+
247
+ @snippets << entry
248
+ end
249
+
250
+ # @!endgroup
251
+
252
+ # ------------------------------------------------------------------
253
+ # @!group controller processes snippets collected
254
+
255
+ # Method called by controller to accept snippets, which snippet
256
+ # plugin has handed over to facade.
257
+ #
258
+ # @param [TlaParserS::Resolver] parserResolver to parse `snippetCode`
259
+ #
260
+
261
+ def acceptSnippets( parserResolver )
262
+
263
+ # resove SPEC_NAMEs and convert 'snippetBody' to
264
+ # 'snippetCode'. Processing continues in block
265
+
266
+ generateSnippetBodies( getMustache ) do |metatype, appName, specName, snippetCode|
267
+ @logger.info( "#{__method__}: process #{metatype}, appName=#{appName}" )
268
+ @logger.debug( "#{__method__}: snippetCode = #{snippetCode}" ) if @logger.debug?
269
+
270
+ # create an single hash holding properties, and which can be
271
+ # also passed to parser.
272
+ parseEntry = parseEntry( metatype, appName, specName, snippetCode )
273
+
274
+ # write to file to the file pointed by modulePath (which is
275
+ # also identified module during parsing)
276
+ writeSnippetModule( parseEntry[:modulePath], snippetCode )
277
+
278
+ # par
279
+ snippets = parserResolver.initSnippets( parseEntry )
280
+ @logger.info "#{__method__}, snippets=#{snippets.map {|s| { :node_type => s[:node_type], :value => s[:value] } } }"
281
+
282
+ # snippetCode should be parseable
283
+ raise Sbuilder::FacadeException.new <<-EOS if snippets.nil? || !snippets.any?
284
+ No snippets found in an entry '#{metatype}:#{appName}':
285
+
286
+ #{snippetCode}
287
+
288
+ EOS
289
+
290
+ # snippet loader can process only one snippet at a time
291
+ raise Sbuilder::FacadeException.new <<-EOS if snippets.length > 1
292
+ Too many snippets defined in an entry
293
+ EOS
294
+
295
+ # extract name && type of the snippet from the parsed result
296
+ snippetName = snippetName( snippets[0] )
297
+ snippetType = snippetType( snippets[0] )
298
+
299
+ # Map snippet type to extension point type, and add the
300
+ # processes snippet as partial to the extension point
301
+ addPartial( parseEntry, snippetType )
302
+
303
+ # add
304
+
305
+ # validate that snippetCode.snippetName == specName
306
+ raise Sbuilder::FacadeException.new <<-EOS if snippetName( snippets[0] ) != specName
307
+ Snippet name '#{ snippetName }' differs from specName '#{specName}' for metatype='#{metatype}', and appName='#{appName}'
308
+
309
+ Difference found in snippet code:
310
+
311
+ #{snippetCode}
312
+ EOS
313
+
314
+ end
315
+
316
+ end
317
+
318
+ # @!endgroup
319
+
320
+ # ------------------------------------------------------------------
321
+ # @!group Support code generation
322
+
323
+ # @return [Object] mustache object configured using 'setMustache'
324
+ private def getMustache
325
+ @mustache
326
+ end
327
+
328
+ # @param [Hash] snippetEntry used to create initial render data
329
+ # @option snippetEntry [String] metatype
330
+ # @option snippetEntry [String] appName
331
+ # @option snippetEntry [String] specName
332
+ private def initialReaderData( snippetEntry )
333
+ snippetEntry
334
+ end
335
+
336
+
337
+
338
+ private def initRenderData
339
+
340
+ end
341
+
342
+ # Create unique specName
343
+ #
344
+ # @param [String] specName, default nil allows sbuilder to generate `specName`
345
+ #
346
+ # @param [String] appName is name application domain being mapped
347
+ # to `specName` in `metatype`
348
+ #
349
+ # @return [String] specName unique name in specification code,
350
+ # mapping result of `metatype` and `appName` combination
351
+
352
+ private def generateSpecName( metatype, appName )
353
+ prefix = metatypePrefix(metatype)
354
+ prefix += "_" unless prefix.blank?
355
+ prefix +
356
+ appName.
357
+ gsub( /\//, "_" ). # / --> _
358
+ gsub( /\(/, "_" ). # ( --> _
359
+ gsub( /\{/, "_" ). # { --> _
360
+ gsub( /\}/, "_" ). # } --> _
361
+ gsub( /\./, "_" ). # . --> _
362
+ gsub( /\)/, "_" ) # ) --> _
363
+
364
+ end
365
+
366
+ # @param [Hash] entry in resolver symbol table
367
+ #
368
+ # @option entry [:symbol] :value key holding parsed snippet name
369
+ #
370
+ # @return [String] snippetName from 'entry' in property :value
371
+ private def snippetName( entry )
372
+ entry[:value]
373
+ end
374
+
375
+ # @param [Hash] entry in resolver symbol table
376
+ #
377
+ # @option entry [:symbol] :node_type key holding parsed snippet class name
378
+ #
379
+ # @return [String] snippetType from 'entry' in property :node_type
380
+ private def snippetType( entry )
381
+ entry[:node_type]
382
+ end
383
+
384
+ # Map 'snippetType' to 'extensionPoint', exception if mapping cannot
385
+ # be made
386
+ private def snippetType2extensionPoint( snippetType )
387
+ extensionPoint = @@snippetType2extensionPointMapper[snippetType]
388
+ raise Sbuilder::FacadeException.new <<-EOS if extensionPoint.nil?
389
+ Unknown snippetType '#{snippetType}'. Do not know, how to map it to extension point.
390
+
391
+ Known node types #{@@snippetType2extensionPointMapper.keys.join( ',' )}
392
+ EOS
393
+ extensionPoint
394
+ end
395
+
396
+ # Use controller to retunn :prefix property in 'metatype'
397
+ # defintion.
398
+ #
399
+ # @return [String] prefix to use for 'metatype'
400
+ private def metatypePrefix( metatype )
401
+
402
+ metatypeDefinition = controller.getMetaTypeDefinition( metatype )
403
+
404
+ raise Sbuilder::FacadeException.new <<-EOS if metatypeDefinition.nil?
405
+ Metatype definition for metatype '#{metatype}' not found
406
+ EOS
407
+
408
+ raise Sbuilder::FacadeException.new <<-EOS unless metatypeDefinition[:prefix]
409
+ Missing property :prefix for metatype '#{metatype}' defined as #{metatypeDefinition}
410
+ EOS
411
+
412
+ return metatypeDefinition[:prefix]
413
+ end
414
+
415
+ # Create hash which can be passed to tla-parser. Particularly this
416
+ # hash defines methods (read, moduleName) used by parser.
417
+ #
418
+ # @return [Hash] parseEntry to pass to parser#initSnippets
419
+ #
420
+ # @option parseEntry [:symbol] code TLA code to parse
421
+ #
422
+ # @option parseEntry [:symbol] name string used to identify 'code'
423
+ #
424
+
425
+ def parseEntry( metatype, appName, specName, snippetCode )
426
+ ret = { :read => snippetCode, :name=> "Api #{metatype}:#{appName}",
427
+ :modulePath => snippetModulePath(metatype, appName, specName ),
428
+ :moduleName => File.join( metatype, specName ),
429
+ }
430
+
431
+ # make it look like a file (supporting read-method)
432
+ ret.define_singleton_method( :read ) do
433
+ self[:read]
434
+ end
435
+ # parser identifies `snippetCode` as module
436
+ ret.define_singleton_method( :modulePath ) do
437
+ self[:modulePath]
438
+ end
439
+ # parser identifies `snippetCode` as module
440
+ ret.define_singleton_method( :moduleName ) do
441
+ self[:moduleName]
442
+ end
443
+
444
+ ret
445
+
446
+ end
447
+
448
+ # Create module path for 'snippetCode'
449
+ #
450
+ # @return [String] modulePath where 'snippetCode' is saved
451
+
452
+ def snippetModulePath( metatype, appName, specName )
453
+ File.join( snippetRepository( metatype ), specName )
454
+ end
455
+
456
+ # @return [String] repositoryPath to root direcnoty under, which
457
+ # to store snippets
458
+ #
459
+ # @param [String] metatype in specification model
460
+ #
461
+ # @return [String] path to an existing snippet direcotory
462
+
463
+ def snippetRepository( metatype )
464
+ snippetRepo = controller.snippetRepository
465
+ controller.metatypeSnippetRepository( snippetRepo, metatype )
466
+ end
467
+
468
+ private def snippetEntry( metatype, appName, snippetBody )
469
+ {
470
+ 'metatype' => metatype,
471
+ 'appName' => appName,
472
+ 'snippetBody' => snippetBody,
473
+ 'specName' => generateSpecName(metatype, appName ),
474
+ }
475
+ end
476
+
477
+ # Iterate 'snippets' handed over to the facade, and use mustache
478
+ # render 'snippetBody' to 'snippetCode'. Typically rendering
479
+ # resolves SPEC_NAME -section used to map application domain names
480
+ # to specification code domain.
481
+ #
482
+ # @yields [metatype,appName,specName,snippetCode] yields
483
+ # 'snippetCode' together with meta data to caller
484
+ #
485
+ #
486
+ private def generateSnippetBodies( mustache, &blk )
487
+
488
+ snippets.each do |snippetEntry|
489
+
490
+ spippetCode = nil
491
+
492
+ # render body - only if defined
493
+ if snippetEntry['snippetBody']
494
+
495
+ @logger.debug "#{__method__}: snippetEntry['snippetBody']=#{snippetEntry['snippetBody']}" if @logger.debug?
496
+
497
+ # create initial hash
498
+ renderData = initialReaderData( snippetEntry )
499
+
500
+ # add functions to renderData allowing access to symbol_table
501
+ # (SPEC_NAME)
502
+ renderData = decorateRenderData( renderData, mustache )
503
+
504
+ # wrap snippet between header/footer, resolve {{mustache}} references
505
+ bodyText = snippetHeader + snippetEntry['snippetBody'] + snippetFooter
506
+ snippetCode = mustache.render( bodyText, renderData )
507
+
508
+ # pass code + meta data to block
509
+ yield snippetEntry['metatype'], snippetEntry['appName'], snippetEntry['specName'], snippetCode
510
+
511
+ end
512
+
513
+ end
514
+
515
+ end
516
+
517
+ # Add functions used in mustache rendering sections to 'renderData'
518
+ #
519
+ # Implementation delegates this task to controller
520
+ #
521
+ # @param [Hash] renderData to decorate
522
+ #
523
+ # @return [Hash] renderData decorated with functions uses in
524
+ # mustache rendering.
525
+ private def decorateRenderData( renderData, mustache )
526
+ controller.decorateRenderData( renderData, mustache )
527
+ end
528
+
529
+ private def addSymbol( metatype, appName, specName )
530
+ controller.getSymbolTable.addSymbol( metatype, appName, specName )
531
+ end
532
+
533
+ # Inform sbuilder for the fact the interface for 'appName' service
534
+ # should call 'specName'.
535
+ #
536
+ # Implementation creates a hash (matching propertis used in
537
+ # 'interface-extension'), and delegates the operation to
538
+ # 'controller.extendInterface'
539
+ #
540
+ # @param [String] extensionType passed to sbuilder defining, what
541
+ # to extend, known cases 'implementation', 'completion'
542
+ #
543
+ #
544
+ private def interfaceExtension( appName, specName, extensionType )
545
+ interfaceExtensionDef = {
546
+ 'matcher' => appName,
547
+ extensionType => specName,
548
+ }
549
+ controller.extendInterface( interfaceExtensionDef )
550
+ end
551
+
552
+ # Mapp 'snippetType' to 'extensionPoint', and add 'parseEntry' to
553
+ # controller partial.
554
+
555
+ private def addPartial( parseEntry, snippetType )
556
+ extensionPoint = snippetType2extensionPoint( snippetType )
557
+ controller.addPartials( [ parseEntry.moduleName ], extensionPoint )
558
+ end
559
+
560
+
561
+ # Write 'snippetCode' to 'modulePath'
562
+ #
563
+ # @param [String] modulePath path to file
564
+ #
565
+ # @param [String] snippetCode contet to write
566
+ #
567
+ #
568
+ private def writeSnippetModule( modulePath, snippetCode )
569
+ @logger.info "#{__method__}, modulePath=#{modulePath}"
570
+ @logger.debug "#{__method__}, modulePath=#{modulePath}, snippetCode=#{snippetCode}"
571
+ Sbuilder::Utils::FileIo.write( modulePath, snippetCode )
572
+ end
573
+
574
+ # @!endgroup
575
+
576
+ # ------------------------------------------------------------------
577
+ # @!group Miscellaneous services
578
+
579
+ # Return cache directory location from opitions
580
+ #
581
+ # @return [String] path to cache -directory
582
+ def getCacheDir
583
+ controller.getCacheDir
584
+ end
585
+
586
+ # @return [String] semver number
587
+ def version
588
+ Sbuilder::version
589
+ end
590
+
591
+ # @param logname [String] progname to set on logger
592
+ #
593
+ # @return [Logger] new logger object
594
+ def createLogger( logname=nil )
595
+ getLogger( logname, @options )
596
+ end
597
+
598
+ end
599
+
600
+ end