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.
- checksums.yaml +4 -4
- data/README.md +150 -116
- data/VERSION +1 -1
- data/lib/cli/cli-customer.rb +23 -3
- data/lib/cli/cli-pet.rb +66 -12
- data/lib/cli/cli-text.rb +127 -8
- data/lib/cli/cli.rb +49 -6
- data/lib/sbuilder.rb +26 -3
- data/lib/sbuilder/constants.rb +165 -6
- data/lib/sbuilder/controller.rb +943 -169
- data/lib/sbuilder/controller_utils.rb +122 -0
- data/lib/sbuilder/default-sbuilder.yaml +38 -44
- data/lib/sbuilder/domain.rb +160 -36
- data/lib/sbuilder/domain_cardinality.rb +1 -1
- data/lib/sbuilder/domain_range.rb +102 -0
- data/lib/sbuilder/domain_type.rb +150 -0
- data/lib/sbuilder/domain_value.rb +21 -13
- data/lib/sbuilder/exception.rb +16 -0
- data/lib/sbuilder/extension_loader.rb +67 -686
- data/lib/sbuilder/extension_loader_deprecated_step_extensions.rb +711 -0
- data/lib/sbuilder/extension_loader_step_generator.rb +876 -0
- data/lib/sbuilder/facade/{api_loader.rb → api_loader_facade.rb} +176 -45
- data/lib/sbuilder/facade/api_loader_plugin.rb +6 -32
- data/lib/sbuilder/facade/api_loader_plugin_mixer.rb +35 -0
- data/lib/sbuilder/facade/facade_constants.rb +23 -0
- data/lib/sbuilder/facade/loader_plugin_root.rb +56 -0
- data/lib/sbuilder/facade/param_set_root.rb +55 -0
- data/lib/sbuilder/facade/snippet_loader_facade.rb +600 -0
- data/lib/sbuilder/facade/snippet_loader_plugin.rb +76 -0
- data/lib/sbuilder/facade/snippet_loader_plugin_mixer.rb +56 -0
- data/lib/sbuilder/factory.rb +224 -45
- data/lib/sbuilder/model.rb +125 -45
- data/lib/sbuilder/mustache/template.rb +107 -58
- data/lib/sbuilder/mustache/template_reader.rb +56 -46
- data/lib/sbuilder/mustache/template_reader_context.rb +64 -234
- data/lib/sbuilder/mustache/template_resolve.rb +103 -0
- data/lib/sbuilder/mustache/template_root.rb +71 -0
- data/lib/sbuilder/param_set.rb +30 -15
- data/lib/sbuilder/param_set_db.rb +1 -1
- data/lib/sbuilder/param_set_def.rb +6 -1
- data/lib/sbuilder/param_set_def_func.rb +39 -0
- data/lib/sbuilder/param_set_if.rb +45 -10
- data/lib/sbuilder/param_set_loader_swagger.rb +56 -26
- data/lib/sbuilder/param_set_step.rb +1 -1
- data/lib/sbuilder/param_sets.rb +2 -1
- data/lib/sbuilder/parameter.rb +9 -3
- data/lib/sbuilder/parameter_container.rb +1 -1
- data/lib/sbuilder/parameter_dom.rb +17 -5
- data/lib/sbuilder/parameter_ref.rb +39 -10
- data/lib/sbuilder/parser/parser_facade.rb +310 -0
- data/lib/sbuilder/resolver.rb +11 -6
- data/lib/sbuilder/resolver_loader.rb +1 -1
- data/lib/sbuilder/resolver_loader_yaml.rb +1 -1
- data/lib/sbuilder/resolver_rule.rb +1 -1
- data/lib/sbuilder/resolver_rule_match.rb +10 -4
- data/lib/sbuilder/resolver_rule_ref.rb +1 -1
- data/lib/sbuilder/setup_loader.rb +49 -0
- data/lib/sbuilder/setup_loader_env.rb +478 -0
- data/lib/sbuilder/setup_loader_pref.rb +56 -0
- data/lib/sbuilder/snippet_loader_simple.rb +125 -0
- data/lib/sbuilder/spec/api_loader.rb +34 -0
- data/lib/sbuilder/spec/api_loader_facade.rb +169 -32
- data/lib/sbuilder/spec/loader_plugin.rb +98 -0
- data/lib/sbuilder/spec/snippet_loader.rb +228 -0
- data/lib/sbuilder/symbol_table.rb +279 -0
- data/lib/utils/{cache_lines.rb → fileio.rb} +8 -1
- data/lib/utils/logger.rb +2 -1
- data/lib/utils/powerset.rb +13 -0
- data/lib/utils/validate.rb +38 -0
- data/mustache/cfg/const_def.mustache +2 -0
- data/mustache/cfg/macro_run.mustache +1 -4
- data/mustache/data-model-header.mustache +1 -0
- data/mustache/definition_types.mustache +34 -4
- data/mustache/domains.mustache +1 -1
- data/mustache/domains_assign.mustache +1 -1
- data/mustache/infrastructure-service-init.mustache +1 -1
- data/mustache/interface_processes.mustache +16 -10
- data/mustache/interface_types.mustache +37 -11
- data/mustache/operator-infrastructure-service.mustache +1 -1
- data/mustache/resources/schedule_operator_new_step.tla +8 -0
- data/mustache/resources/schedule_process_macro.tla +37 -0
- data/mustache/resources/schedule_process_procedure.tla +22 -0
- data/mustache/resources/schedule_throw.tla +16 -0
- data/mustache/setup/domains_run.mustache +8 -2
- data/mustache/setup/operator_run.mustache +0 -4
- data/mustache/setup/steps_run.mustache +4 -3
- data/mustache/setup/steps_run_parameterBind.mustache +14 -6
- data/mustache/setup/steps_run_parameterExact.mustache +7 -3
- data/mustache/state_type_invariant-infrastructure-service.mustache +9 -4
- data/mustache/tla/const_def.mustache +1 -1
- data/mustache/tla/macro_run.mustache +7 -1
- data/mustache/tla/module_header.mustache +1 -1
- data/mustache/tla/operator_run.mustache +8 -5
- data/mustache/tla/plc_define_run.mustache +45 -36
- data/mustache/tla/plc_run_state.mustache +12 -5
- data/src-extend/extend/extend_assumptions.mustache +3 -0
- data/src-extend/extend/extend_const.mustache +3 -0
- data/src-extend/extend/extend_implementation.mustache +3 -0
- data/src-extend/extend/extend_invariant.mustache +3 -0
- data/src-extend/extend/extend_macros.mustache +3 -0
- data/src-extend/extend/extend_operations.mustache +3 -0
- data/src-extend/extend/extend_state.mustache +3 -0
- data/src/pet/extend/extend_assumptions.mustache +4 -0
- data/src/pet/extend/extend_implementation.mustache +3 -0
- data/src/pet/extend/extend_invariant.mustache +3 -0
- data/src/pet/extend/extend_macros.mustache +3 -0
- data/src/pet/extend/extend_operations.mustache +4 -0
- data/src/pet/extend/extend_state.mustache +3 -0
- data/src/pet/interface +5 -5
- data/src/pet/interface_delete_pet.tla +1 -1
- data/src/pet/interface_get_pet.tla +1 -1
- data/src/pet/interface_post_pet.tla +4 -2
- data/src/pet/interface_post_tag.tla +1 -1
- data/src/pet/interface_put_tag.tla +1 -1
- data/tla-sbuilder.gemspec +3 -3
- metadata +44 -19
- data/mustache/name_definition_type.mustache +0 -5
- data/mustache/name_domain.mustache +0 -5
- data/mustache/name_domain_value.mustache +0 -5
- data/mustache/name_domain_value_prefix.mustache +0 -5
- data/mustache/name_interface_response_type.mustache +0 -6
- data/mustache/name_interface_type.mustache +0 -6
- data/mustache/name_parameter_type.mustache +0 -6
- data/mustache/name_process.mustache +0 -6
- data/mustache/state_type_invariant.mustache +0 -17
- data/mustache/state_variables.mustache +0 -20
- 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
|