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
  module Sbuilder
2
3
 
3
4
  class Model
@@ -12,14 +13,17 @@ module Sbuilder
12
13
  attr_reader :possibilities # [String:Array] possibilities in setup
13
14
  attr_reader :invariants # [Hash:Array] properties 'name', 'desc'
14
15
  attr_reader :setupDef # [Hash] properties 'setupDirectory', 'desc', 'extensions'
15
- attr_reader :assumptions # [Hash:Array] properties 'name', 'desc'
16
+ attr_reader :assumptions # [Hash:Array] properties 'name', 'desc'
17
+
18
+ # @əttr [domainDef:Array] applicationDomainValues to pass to 'dispatchExtendDomain'
19
+ attr_reader :applicationDomainValues
16
20
 
17
21
  # ------------------------------------------------------------------
18
22
  # mixer
19
- PROGNAME = "Model" # progname for logger
23
+ PROGNAME = nil # progname for logger default class name
20
24
  include Sbuilder::Utils::MyLogger # mix logger
21
25
 
22
- @@validInterfaceExtensionProperties = ["matcher", "implementation"]
26
+ # @@validInterfaceExtensionProperties = ["matcher", "implementation"]
23
27
 
24
28
  # ------------------------------------------------------------------
25
29
  # constructore
@@ -42,7 +46,8 @@ module Sbuilder
42
46
  @invariants = []
43
47
  @assumptions = []
44
48
  @interfaceExtensions = {}
45
-
49
+ @symbolTable = nil
50
+ @applicationDomainValues = []
46
51
 
47
52
  end
48
53
 
@@ -91,6 +96,17 @@ module Sbuilder
91
96
 
92
97
  return ret
93
98
  end
99
+
100
+
101
+ # ------------------------------------------------------------------
102
+ # synbol table stuff
103
+
104
+
105
+ # @return [Sbuilder::SymbolTable] symbolTable for the model
106
+ def getSymbolTable
107
+ # init only once
108
+ @symbolTable = @symbolTable || factory.createSymbolTable
109
+ end
94
110
 
95
111
 
96
112
  # ------------------------------------------------------------------
@@ -108,6 +124,17 @@ module Sbuilder
108
124
  return createOrUpdateDomain( domainName, nil )
109
125
  end
110
126
 
127
+ ##
128
+ # Add application model domain value definition to an array.
129
+ # These are later (during setup phase) used to extend domains.
130
+ #
131
+ #
132
+ # @param [Hash] domainDef to pass to dispatchExtendDomain
133
+ #
134
+ # @see dispatchExtendDomain
135
+ def addApplicationDomainValue( domainDef )
136
+ @applicationDomainValues << domainDef
137
+ end
111
138
 
112
139
  # called from a separte plase
113
140
  def extendDomain( domain )
@@ -115,7 +142,7 @@ module Sbuilder
115
142
  raise ModelException.new <<-EOS unless domains[domain.name]
116
143
  Unknown domain.name=#{domain.name}
117
144
 
118
- Trying to extend domain '#{domain.name}', which not among resolved domains.
145
+ Trying to extend domain '#{domain.name}', which is not known.
119
146
 
120
147
  Known domain names are: #{domains.keys.join(', ' )}
121
148
 
@@ -177,21 +204,24 @@ module Sbuilder
177
204
 
178
205
 
179
206
  # extend
207
+ # @param [Hash] interfaceExtensionDef
208
+ # @option [String] matcher
209
+ # @option [Sting] implementation
180
210
  def extendInterface( interfaceExtensionDef )
181
211
 
182
212
  # validate properties 'interfaceExtensionDef'
183
213
  begin
184
- validateProperties( interfaceExtensionDef, @@validInterfaceExtensionProperties )
214
+ Utils::Validate.validateProperties( interfaceExtensionDef, Constants::VALIDATION[:interface_extension_def][:required], Constants::VALIDATION[:interface_extension_def][:allowed] )
215
+ # validateProperties( interfaceExtensionDef, @@validInterfaceExtensionProperties )
185
216
  rescue ModelException => me
186
217
  @logger.info( "#{__method__} model exception #{me}" )
187
218
  raise ExtensionException.new( me )
188
219
  end
189
-
190
220
  # locate interface being extended
191
221
  interfaceParamSet = getInterface( interfaceExtensionDef['matcher'] )
192
222
 
193
223
  # record extension in '@interfaceExtensions'
194
- putImplementationExtension( interfaceParamSet, interfaceExtensionDef )
224
+ mergeImplementationExtension( interfaceParamSet, interfaceExtensionDef )
195
225
 
196
226
  # return the extended interface
197
227
  interfaceParamSet
@@ -220,16 +250,31 @@ module Sbuilder
220
250
 
221
251
  end
222
252
 
223
- # record extension in '@interfaceExtensions'
224
- def putImplementationExtension( interfaceParamSet, interfaceExtensionDef )
225
- @interfaceExtensions[interfaceParamSet.getId] = interfaceExtensionDef
253
+ # record extension in '@interfaceExtensions' (merge with previos props)
254
+ # @param [Hash] interfaceExtensionDef
255
+ # @option interfaceExtensionDef [String] implementation
256
+ # @option interfaceExtensionDef [String] completion
257
+ def mergeImplementationExtension( interfaceParamSet, interfaceExtensionDef )
258
+ @interfaceExtensions[interfaceParamSet.getId] = ( @interfaceExtensions[interfaceParamSet.getId] || {} ).merge interfaceExtensionDef
226
259
  end
227
260
 
228
- # provide information on extension implementation during generation phase
261
+ # extension interface service implementation, accessed during generation phase
229
262
  def getImplementationExtension( interfaceParamSet )
230
- interfaceExtensions[interfaceParamSet.getId] ? interfaceExtensions[interfaceParamSet.getId]['implementation'] : nil
263
+ doGetInterfaceExtension( interfaceParamSet, 'implementation' )
264
+ end
265
+
266
+ # extension to complete interface service implementation, accessed during generation phase
267
+ def getCompletionExtension( interfaceParamSet )
268
+ doGetInterfaceExtension( interfaceParamSet, 'completion' )
231
269
  end
232
270
 
271
+ ##
272
+ # @return 'key' property from from 'interfaceExtensions' for 'interfaceParamSet.getId', or false
273
+ private def doGetInterfaceExtension( interfaceParamSet, key )
274
+ interfaceExtensions[interfaceParamSet.getId] ? interfaceExtensions[interfaceParamSet.getId][key] : false
275
+ end
276
+
277
+
233
278
  # array of known interface ids
234
279
  def interfaceIds
235
280
  interfaces.values.map { |interface| interface.getId }
@@ -273,27 +318,38 @@ module Sbuilder
273
318
  #
274
319
  #
275
320
 
276
- # return hash for mustache for 'templateName' in 'interfaces', 'domains', 'variables'
321
+ # @param [String] domainName in data model
322
+ #
323
+ # @return [Hash] dataModelElement for mustache for 'templateName' in 'interfaces', 'domains', 'variables' etc
324
+ #
325
+ # @option dataModelElement [String] dump to output data array
326
+ #
327
+ # @option dataModelElement [String] symbols optional lambda
328
+ # function to map data array to symbol table definitions
329
+ #
330
+ # @option dataModelElement [String] 'domainName' data array for
331
+ # element in model for domainName
332
+
277
333
  def templateData( domainName )
278
334
 
279
335
  case domainName
280
336
  when 'interfaces'
281
337
  # see domainName 'interfaces'
282
338
  templateDataInterfaces( domainName, false )
283
- when 'interface_types'
284
- # see domainName 'interfaces', interface_types are not
285
- # filtered i.e. generated model defines data types for all interfaces
286
- templateDataInterfaces( 'interfaces', false )
339
+ # when 'interface_types'
340
+ # # see domainName 'interfaces', interface_types are not
341
+ # # filtered i.e. generated model defines data types for all interfaces
342
+ # templateDataInterfaces( 'interfaces', false )
287
343
  when 'infrastructureServices'
288
344
  templateDataInterfaces( domainName, true )
289
345
  when 'possibility'
290
346
  hash = {
291
- "possibility" => lambda { hash['possibility'].to_yaml },
347
+ "dump" => lambda { hash['possibility'].to_yaml },
292
348
  "possibility" => possibility, # possibility defined in setup, currently being generated
293
349
  }
294
350
  when 'possibilities'
295
351
  hash = {
296
- "possibilities" => lambda { hash['possibilities'].to_yaml },
352
+ "dump" => lambda { hash['possibilities'].to_yaml },
297
353
  "possibilities" => possibilities, # possibilities in setup, all in current setup
298
354
  }
299
355
  when 'variables'
@@ -311,9 +367,10 @@ module Sbuilder
311
367
  :interface_operation => step.interfaceReference.getId,
312
368
  :interface_path => step.interfaceReference.path,
313
369
  # :interface_id => step.interfaceReference.getId,
314
- :_comma => (i< steps.length-1 ? "," : ""),
370
+ '_comma' => (i< steps.length-1 ? "," : ""),
315
371
  :bindRule => step.bindExact == false ? step.inputs : false,
316
- :bindSets => step.bindExact ? step.inputs.map.with_index { |input,i| input[:_comma] = i<step.inputs.length-1 ? ',' : ''; input } : false,
372
+ # :bindSets => step.bindExact ? step.inputs.map.with_index { |input,i| input['_comma'] = i<step.inputs.length-1 ? ',' : ''; input } : false,
373
+ :bindSets => step.bindExact ? step.inputs : false,
317
374
  }
318
375
  },
319
376
  }
@@ -330,30 +387,47 @@ module Sbuilder
330
387
  "dump" => lambda { hash['assumptions'].to_yaml },
331
388
  "assumptions" => assumptions,
332
389
  }
390
+
333
391
  when 'definitions'
334
392
  hash = {
335
- "dump" => lambda { hash['definitions'].to_yaml },
336
- "definitions" => definitions.tsort.map.with_index { |parameterName,i|
393
+ "dump" => lambda { hash['definitions'].to_yaml },
394
+ # "symbols" => ->( d ) { [
395
+ # Sbuilder::Constants::META_MODEL_DEFINITION,
396
+ # d[:definition_name],
397
+ # d[:definition_name]
398
+ # ] },
399
+ 'definitions' => definitions.tsort.map.with_index { |parameterName,i|
337
400
  # tsort returns array of names, resolve paramSet
338
401
  p = getParamset( parameterName )
339
402
  { :definition_name => p.getName,
340
403
  :isArray => p.isArray,
341
- :_comma => (i< definitions.values.length-1 ? "," : ""),
404
+ :domainParameters => p.isFunction ? p.parameter_definitions( self, p.domainParameters ) : [],
405
+ :rangeParameters => p.isFunction ? p.parameter_definitions( self, p.rangeParameters ) : [],
406
+ :isFunction => p.isFunction,
407
+ '_comma' => (i< definitions.values.length-1 ? "," : ""),
342
408
  :parameter_definitions => p.parameter_definitions( self )
343
409
  }
344
410
  }
345
411
  } # => TLA definitions
346
412
  when 'domains'
347
413
  hash = {
348
- "dump" => lambda { hash['domains'].to_yaml },
414
+ "dump" => lambda { hash['domains'].to_yaml },
349
415
  "domains" => domains.values.map do |domain|
350
416
  {
351
417
  :domain_name => domain.domain_name,
352
- :nil_value => setup_nil_values,
418
+ # Nil included: if global configuration does not prevent && domain uses nil
419
+ :nil_value => setup_nil_values && domain.includeNil,
420
+ :tlaBaseType => domain.tlaBaseType,
353
421
  :domain_values => domain.domain_values,
354
422
  }
355
423
  end, # => TLA domain
356
424
  }
425
+ when 'metatypes'
426
+ hash = {
427
+ "dump" => lambda { hash['metatypes'].to_yaml },
428
+ "metatypes" => getSymbolTable.metatypes
429
+ }
430
+
357
431
  else
358
432
  raise "Unknown template '#{domainName}'"
359
433
  end # case
@@ -363,37 +437,43 @@ module Sbuilder
363
437
 
364
438
  # Extract data model for interfaces
365
439
  #
366
- # @param infrastructureServices [Boolean] choose 'interfaces' or 'infrastructureServices'
367
- # @return [Hash] for template rendering composed of interfaces, false if configs
440
+ # @param [Boolean] choose false --> interterfaces with 'interfaceService', true => 'infrastructureService'
441
+ #
442
+ # @return [Hash] for template rendering composed of interfaces, 'false' if configs
368
443
  #
369
- private def templateDataInterfaces( domainName, infrastructureServices )
444
+ private def templateDataInterfaces( domainName, choose )
370
445
  hash = {
371
- "dump" => lambda { hash[domainName].to_yaml },
372
- domainName => interfaces.values.select { |iface|
446
+ "dump" => lambda { hash[domainName].to_yaml },
447
+
448
+ domainName => interfaces.values.select { |iface|
373
449
 
374
- iface.infrastructureService == infrastructureServices
450
+ !choose && iface.interfaceService ||
451
+ choose && iface.infrastructureService
375
452
 
376
- }.map { |iface |
377
- {
378
- :interface_name => iface.getName, # e.g._pet_post_
379
- :interface_operation => iface.getId, # e.g /pet(post)
380
- :implementation => getImplementationExtension( iface ),
381
- :_comma => ',',
382
- :parameter_definitions => iface.parameter_definitions( self ),
383
- :response_definitions => iface.response && iface.response.parameters.any? ? iface.response.parameter_definitions( self ) : false,
384
- }
385
- } # => TLA process & stubs
453
+ }.map { |iface |
454
+ {
455
+ :interface_name => iface.getName, # e.g._pet_post_
456
+ :interface_operation => iface.getId, # e.g /pet(post)
457
+ :implementation => getImplementationExtension( iface ),
458
+ :completion => getCompletionExtension( iface ),
459
+ '_comma' => ',',
460
+ :parameter_definitions => iface.parameter_definitions( self ),
461
+ :response_definitions => iface.response && iface.response.parameters.any? ? iface.response.parameter_definitions( self ) : false,
462
+ }
463
+ } # => TLA process & stubs
386
464
  }
387
465
 
388
466
  # return 'false' instead of an array if empty
389
467
  hash[domainName] = false unless hash[domainName].any?
390
- # fix _comma for the last entry in array
468
+ # fix _comma = "" for the last entry in array
391
469
  fixLastComma( hash[domainName] )
392
470
  return hash
393
471
  end
394
472
 
473
+ # @return [Hash:Array] with _comma property set to '' for the
474
+ # last element in the array
395
475
  private def fixLastComma( arrOfHashes )
396
- arrOfHashes.last[:_comma] = "" if arrOfHashes && arrOfHashes.any?
476
+ arrOfHashes.last['_comma'] = "" if arrOfHashes && arrOfHashes.any?
397
477
  end
398
478
 
399
479
 
@@ -1,11 +1,10 @@
1
- require 'mustache' # extendending implementation of
2
-
3
1
  module Sbuilder
4
2
 
5
- class Template < Mustache
3
+
4
+ class Template < TemplateRoot
6
5
 
7
6
  include Sbuilder::Utils::MyLogger # mix logger
8
- PROGNAME = "template" # progname for logger
7
+ PROGNAME = nil
9
8
 
10
9
 
11
10
  # ------------------------------------------------------------------
@@ -13,16 +12,11 @@ module Sbuilder
13
12
 
14
13
  # instance
15
14
  attr_writer :partials # f: partial-name --> template string
16
- attr_reader :reader # Sbuilder::TemplateReader implementing
17
- # 'get_template', 'get_template_filepath'
18
-
19
- extend Forwardable # for easy delegation
20
- def_delegators :reader,:get_template, :get_template_filepath, :configSetup, :template_read
21
-
22
15
  # ------------------------------------------------------------------
23
16
  # Constructor
24
17
 
25
18
  def initialize( reader, options={} )
19
+ super( reader, options )
26
20
  @logger = getLogger( PROGNAME, options )
27
21
  @logger.info( "#{__method__} created" )
28
22
  @logger.debug( "#{__method__}, options='#{options}" )
@@ -30,59 +24,130 @@ module Sbuilder
30
24
  # init partial cache
31
25
  @partials = {}
32
26
 
33
- # inject reader
34
- #@reader = Sbuilder::TemplateReader.new( options )
35
- @reader = reader
27
+ # inidirection data init to empty hash
28
+ setData( {} )
29
+
36
30
 
37
31
  end
38
32
 
39
33
  # ------------------------------------------------------------------
40
34
  # Services
41
35
 
36
+ # Return extension point for 'template_name' mustache template as
37
+ # string.
38
+ #
39
+ # Implemtation return a string including mustache partial calls
40
+ # '{{>partial}}' for entries in array read from controller
41
+ # using method 'getExtensionPointPartials'.
42
+ #
43
+ # @param template_name [String] template for extension point
44
+ #
45
+ private def extension_template( template_name )
46
+ extensionTemplates = controller.getExtensionPointPartials( template_name )
47
+ @logger.info "#{__method__} Create extension_template for #{template_name} with #{extensionTemplates.join(',')}"
48
+ str=<<-EOS
49
+ {{! Generated in #{__FILE__} in #{__method__} }}
50
+
51
+ \\* Extension point template #{template_name}:
52
+
53
+ #{
54
+ extensionTemplates.map{ |p| '{{>' + p + '}}' }.join( "\n")
55
+ }
56
+ EOS
57
+ @logger.debug "#{__method__} template #{template_name} is #{str}" if @logger.debug?
58
+ str
59
+ end
60
+
61
+
42
62
  def to_str( template_name, data )
43
63
  @logger.info( "#{__method__}: template_name=#{template_name}" )
44
64
  @logger.debug( "#{__method__}: template_name=#{template_name}" ) if @logger.debug?
45
65
  # @logger.debug( "#{__method__}: nodes=#{data.nodes}" )
46
66
 
47
- # data = add_dynamic_load( data )
48
-
49
- @data = data
67
+ # parent class keeps tract of data, and get_template may need it
68
+ # for indirection
69
+ setData( data )
70
+
71
+ if is_extension_point( template_name ) then
72
+ #
73
+ # Use a dynamically created string to output extension points
74
+ #
75
+ template = extension_template( template_name )
76
+ @logger.debug "#{__method__} template: is extension #{template_name} -> #{template}" if @logger.debug?
77
+
78
+ else
79
+
80
+ # reader in parent class returns template to resolve as a
81
+ # string.
82
+ #
83
+ # Normally reads template from file to which 'template_name'
84
+ # resolves. It may be also an empty string (if reader has
85
+ # decided that 'template_name' should not be shown.
86
+ template = get_template( template_name )
87
+ @logger.debug "#{__method__} template: is not extension #{template_name} -> #{template}" if @logger.debug?
88
+ # render( template, @data )
89
+ end
50
90
 
51
- template = get_template( template_name )
52
91
  # render( template, @data )
53
-
54
- render( template, @data )
92
+ render_str( template, data )
55
93
  end
56
94
 
95
+
96
+ # @param template [String] mustache template used to render
97
+ # @param data [Hash] data to render
57
98
  def render_str( template, data )
58
99
  render( template, data )
59
100
  end
60
101
 
61
- # ------------------------------------------------------------------
62
- # Integrate with mustache
102
+ # Method called from concrete sub-class before rendering start.
103
+
104
+ # @param data [Hash] data being rendered
105
+ def setData( data={} )
106
+ @data = data
107
+ end
108
+
109
+ # @attr [Hash] data stored in concrete class, enable indirection
110
+ # using lambda function
111
+ def data
112
+ return @data
113
+ end
114
+
115
+
116
+
63
117
 
64
- # method used by mustache framework - delegate to 'get_partial'
65
- def partial(name)
118
+ # ------------------------------------------------------------------
119
+ # @!group Called from 'partial' -method
120
+
121
+ # Intercept chain to read template file, and cache @partials.
122
+ #
123
+ # Delegates actual read operation to 'get_template' in parent
124
+ # class reader.
125
+ #
126
+ # @param name [String] name of partial template to include
127
+ def get_partial( name )
66
128
  @logger.debug( "#{__method__} name=#{name}" )
129
+ # return indirection for 'name[2..-1]) ' if name[0..1] == '!!'
130
+ name = resolve_partial_name(name)
131
+ return @partials[name] if @partials[name]
132
+ @logger.info( "#{__method__} read partial_file=#{name}" )
133
+
134
+ @partials[name] = get_template( name )
135
+ return @partials[name]
67
136
 
68
- # return resolve_partial_direct(name[2..-1]) if name[0..1] == '!!'
69
- get_partial( resolve_partial_name(name) )
70
137
  end
71
138
 
72
- # #
73
- # # @param path_template [String] mustache template string to intepret for path
74
- # #
75
- # # @return [String] content of file pointed by rendering 'path_template'
76
- # def resolve_partial_direct( path_template )
77
- # # change mustache delimerters to allow rendering
78
- # # templ = "{{=%% %%=}}#{path_template}<%={{ }}=%>"
79
- # puts path_template
80
- # templ = path_template
81
- # path = render( templ, @data )
82
- # template_read( path )
83
- # end
84
-
85
- # lookup
139
+ # @!endgroup
140
+
141
+ # ------------------------------------------------------------------
142
+ # @!group private
143
+
144
+ # Return name of partial, which normally is simply 'name'
145
+ # parameer, but which can be found form '@data' using indirect
146
+ # address following starting exclamation mark.
147
+ #
148
+ # @return [String] 'name' or value from '@data' pointed by name
149
+ # minus prefixed exclamation
150
+
86
151
  def resolve_partial_name( name )
87
152
  return name unless name[0..0] == '!'
88
153
  # remove !, split, and use injected traves to access data
@@ -98,25 +163,9 @@ module Sbuilder
98
163
  @logger.info( "#{__method__} name=#{name} --> #{ret}" )
99
164
  ret
100
165
  end
101
-
102
- # ------------------------------------------------------------------
103
- # Cache partials once resoved
104
-
105
- # cache @partials - for easier extension
106
- def get_partial( name )
107
- @logger.debug( "#{__method__} name=#{name}" )
108
- return @partials[name] if @partials[name]
109
- @logger.info( "#{__method__} read partial_file=#{name}" )
110
-
111
- @partials[name] = get_template( name )
112
- return @partials[name]
113
-
114
- # partial_file = get_template_filepath( name )
115
- # @logger.info( "#{__method__} read partial_file=#{partial_file}" )
116
- # @partials[name] = File.read( partial_file )
117
- # @partials[name]
118
- end
119
-
166
+
167
+
168
+
120
169
 
121
170
  end # class
122
171