tla-sbuilder 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +328 -0
- data/VERSION +1 -0
- data/bin/sbuilder.rb +5 -0
- data/lib/cli/cli-customer.rb +420 -0
- data/lib/cli/cli-example.rb +92 -0
- data/lib/cli/cli-pet.rb +767 -0
- data/lib/cli/cli-text.rb +226 -0
- data/lib/cli/cli.rb +298 -0
- data/lib/sbuilder.rb +52 -0
- data/lib/sbuilder/constants.rb +72 -0
- data/lib/sbuilder/controller.rb +798 -0
- data/lib/sbuilder/default-sbuilder.yaml +372 -0
- data/lib/sbuilder/domain.rb +124 -0
- data/lib/sbuilder/domain_cardinality.rb +37 -0
- data/lib/sbuilder/domain_value.rb +81 -0
- data/lib/sbuilder/exception.rb +27 -0
- data/lib/sbuilder/extension_loader.rb +721 -0
- data/lib/sbuilder/factory.rb +234 -0
- data/lib/sbuilder/model.rb +356 -0
- data/lib/sbuilder/mustache/template.rb +125 -0
- data/lib/sbuilder/mustache/template_reader.rb +206 -0
- data/lib/sbuilder/mustache/template_reader_context.rb +371 -0
- data/lib/sbuilder/param_set.rb +132 -0
- data/lib/sbuilder/param_set_db.rb +20 -0
- data/lib/sbuilder/param_set_def.rb +57 -0
- data/lib/sbuilder/param_set_if.rb +68 -0
- data/lib/sbuilder/param_set_loader.rb +77 -0
- data/lib/sbuilder/param_set_loader_swagger.rb +424 -0
- data/lib/sbuilder/param_set_step.rb +62 -0
- data/lib/sbuilder/param_sets.rb +54 -0
- data/lib/sbuilder/parameter.rb +97 -0
- data/lib/sbuilder/parameter_container.rb +72 -0
- data/lib/sbuilder/parameter_dom.rb +70 -0
- data/lib/sbuilder/parameter_ref.rb +71 -0
- data/lib/sbuilder/resolver.rb +78 -0
- data/lib/sbuilder/resolver_loader.rb +79 -0
- data/lib/sbuilder/resolver_loader_yaml.rb +103 -0
- data/lib/sbuilder/resolver_rule.rb +36 -0
- data/lib/sbuilder/resolver_rule_match.rb +55 -0
- data/lib/sbuilder/resolver_rule_ref.rb +37 -0
- data/lib/utils/hash_inject.rb +12 -0
- data/lib/utils/logger.rb +80 -0
- data/lib/utils/netio.rb +58 -0
- data/lib/utils/string_inject.rb +10 -0
- data/lib/utils/version.rb +13 -0
- data/mustache/cfg/const_def.mustache +8 -0
- data/mustache/cfg/const_run.mustache +3 -0
- data/mustache/cfg/invariant-infrastructure-service.mustache +4 -0
- data/mustache/cfg/macro_run.mustache +6 -0
- data/mustache/cfg/module_footer.mustache +0 -0
- data/mustache/cfg/module_header.mustache +7 -0
- data/mustache/data-model-dump.mustache +19 -0
- data/mustache/data-model-footer.mustache +5 -0
- data/mustache/data-model-header.mustache +16 -0
- data/mustache/definition_types.mustache +40 -0
- data/mustache/domains.mustache +20 -0
- data/mustache/domains_assign.mustache +22 -0
- data/mustache/domains_run.mustache +21 -0
- data/mustache/extend/extend_assumptions.mustache +7 -0
- data/mustache/extend/extend_const.mustache +5 -0
- data/mustache/extend/extend_implementation.mustache +9 -0
- data/mustache/extend/extend_invariant.mustache +7 -0
- data/mustache/extend/extend_invariant_cfg.mustache +7 -0
- data/mustache/extend/extend_macros.mustache +19 -0
- data/mustache/extend/extend_operations.mustache +9 -0
- data/mustache/extend/extend_state.mustache +9 -0
- data/mustache/infrastructure-service-init.mustache +36 -0
- data/mustache/infrastructure-service-variables.mustache +10 -0
- data/mustache/interface_processes.mustache +38 -0
- data/mustache/interface_stubs_dummy.mustache +13 -0
- data/mustache/interface_types.mustache +52 -0
- data/mustache/markdown-header.mustache +24 -0
- data/mustache/markdown-toc.mustache +13 -0
- data/mustache/name_definition_type.mustache +5 -0
- data/mustache/name_domain.mustache +5 -0
- data/mustache/name_domain_value.mustache +5 -0
- data/mustache/name_domain_value_prefix.mustache +5 -0
- data/mustache/name_interface_response_type.mustache +6 -0
- data/mustache/name_interface_type.mustache +6 -0
- data/mustache/name_parameter_definition.mustache +5 -0
- data/mustache/name_parameter_type.mustache +6 -0
- data/mustache/name_process.mustache +6 -0
- data/mustache/name_type_invariant.mustache +5 -0
- data/mustache/name_variable.mustache +6 -0
- data/mustache/operator-infrastructure-service.mustache +13 -0
- data/mustache/possibility/module_extends.mustache +1 -0
- data/mustache/possibility/module_footer.mustache +1 -0
- data/mustache/possibility/module_header.mustache +8 -0
- data/mustache/possibility/possibility_definition.mustache +12 -0
- data/mustache/possibility/possibility_directive.mustache +1 -0
- data/mustache/possibility/possility_setup.mustache +28 -0
- data/mustache/setup/module_footer.mustache +1 -0
- data/mustache/setup/module_header.mustache +9 -0
- data/mustache/setup/operator_run.mustache +7 -0
- data/mustache/setup/operator_tick.mustache +2 -0
- data/mustache/setup/steps_run.mustache +22 -0
- data/mustache/setup/steps_run_bind_rule.mustache +51 -0
- data/mustache/setup/steps_run_bind_set.mustache +37 -0
- data/mustache/setup/steps_run_parameterBind.mustache +80 -0
- data/mustache/setup/steps_run_parameterExact.mustache +79 -0
- data/mustache/state_type_invariant-infrastructure-service.mustache +49 -0
- data/mustache/state_type_invariant.mustache +17 -0
- data/mustache/state_type_invariant_cfg.mustache +18 -0
- data/mustache/state_variables.mustache +20 -0
- data/mustache/tla/const_def.mustache +5 -0
- data/mustache/tla/const_run.mustache +3 -0
- data/mustache/tla/macro-infrastructure-service.mustache +14 -0
- data/mustache/tla/macro_run.mustache +40 -0
- data/mustache/tla/module_footer.mustache +2 -0
- data/mustache/tla/module_header.mustache +9 -0
- data/mustache/tla/operator_run.mustache +8 -0
- data/mustache/tla/operators-infrastructure-service.mustache +12 -0
- data/mustache/tla/plc_define_footer.mustache +1 -0
- data/mustache/tla/plc_define_header.mustache +1 -0
- data/mustache/tla/plc_define_run.mustache +59 -0
- data/mustache/tla/plc_footer.mustache +2 -0
- data/mustache/tla/plc_header.mustache +2 -0
- data/mustache/tla/plc_run_state.mustache +12 -0
- data/mustache/tla/plc_tail.mustache +8 -0
- data/mustache/tla/plc_translation.mustache +2 -0
- data/resources/schema/json_schema/draft-04.json +150 -0
- data/resources/schema/swagger/2.0/schema.json +1591 -0
- data/src-extend/README +2 -0
- data/src-extend/extend/extend_assumptions.mustache +7 -0
- data/src-extend/extend/extend_const.mustache +5 -0
- data/src-extend/extend/extend_implementation.mustache +9 -0
- data/src-extend/extend/extend_invariant.mustache +11 -0
- data/src-extend/extend/extend_invariant_cfg.mustache +7 -0
- data/src-extend/extend/extend_macros.mustache +19 -0
- data/src-extend/extend/extend_operations.mustache +9 -0
- data/src-extend/extend/extend_state.mustache +9 -0
- data/src-extend/extend_app/assumption +20 -0
- data/src-extend/extend_app/correctness +19 -0
- data/src-extend/extend_app/correctness.cfg +9 -0
- data/src-extend/extend_app/infrastructure +25 -0
- data/src-extend/extend_app/interface +11 -0
- data/src-extend/extend_app/operator +18 -0
- data/src-extend/extend_app/possibility +16 -0
- data/src-extend/extend_app/service +33 -0
- data/src-extend/extend_app/state +16 -0
- data/src-extend/extend_app/transaction +22 -0
- data/src/pet/assumption +29 -0
- data/src/pet/assumption_address_domains.tla +12 -0
- data/src/pet/assumption_domains.tla +16 -0
- data/src/pet/assumption_generic.tla +8 -0
- data/src/pet/assumption_id_domains.tla +2 -0
- data/src/pet/assumption_owner_domains.tla +14 -0
- data/src/pet/assumption_pet_domains.tla +16 -0
- data/src/pet/assumption_tag_domains.tla +13 -0
- data/src/pet/correctness +24 -0
- data/src/pet/correctness.cfg +9 -0
- data/src/pet/correctness_coherent_owner_address.tla +6 -0
- data/src/pet/correctness_pet_name.tla +4 -0
- data/src/pet/correctness_ref_tag.tla +13 -0
- data/src/pet/correctness_type_invariants.tla +12 -0
- data/src/pet/correctness_unique_pet.tla +3 -0
- data/src/pet/correctness_unique_tag.tla +3 -0
- data/src/pet/docs/Petstore.md +117 -0
- data/src/pet/extend/extend_assumptions.mustache +7 -0
- data/src/pet/extend/extend_implementation.mustache +9 -0
- data/src/pet/extend/extend_invariant.mustache +11 -0
- data/src/pet/extend/extend_invariant_cfg.mustache +7 -0
- data/src/pet/extend/extend_macros.mustache +19 -0
- data/src/pet/extend/extend_operations.mustache +9 -0
- data/src/pet/extend/extend_state.mustache +9 -0
- data/src/pet/infrastructure +25 -0
- data/src/pet/infrastructure_id_get.tla +24 -0
- data/src/pet/interface +12 -0
- data/src/pet/interface_delete_pet.tla +5 -0
- data/src/pet/interface_get_pet.tla +4 -0
- data/src/pet/interface_post_pet.tla +5 -0
- data/src/pet/interface_post_tag.tla +5 -0
- data/src/pet/interface_put_tag.tla +3 -0
- data/src/pet/operator +30 -0
- data/src/pet/operator_find_tag_by_owner_name.tla +1 -0
- data/src/pet/operator_get_pet.tla +4 -0
- data/src/pet/operator_get_pet_by_tag.tla +4 -0
- data/src/pet/operator_get_tag.tla +10 -0
- data/src/pet/operator_new_owner.tla +3 -0
- data/src/pet/operator_new_pet.tla +13 -0
- data/src/pet/operator_new_tag.tla +3 -0
- data/src/pet/operator_next_pet_id.tla +3 -0
- data/src/pet/operator_responses.tla +8 -0
- data/src/pet/operator_tag_exists.tla +2 -0
- data/src/pet/operator_tag_owner_validated.tla +2 -0
- data/src/pet/operator_tag_referenced.tla +4 -0
- data/src/pet/operator_valid_owner.tla +17 -0
- data/src/pet/operator_valid_pet.tla +6 -0
- data/src/pet/operator_valid_tag.tla +5 -0
- data/src/pet/possibility +18 -0
- data/src/pet/possibility_at_least_two_tags.tla +12 -0
- data/src/pet/possibility_invalid_tag_address.tla +8 -0
- data/src/pet/service +35 -0
- data/src/pet/service_pet_delete.tla +11 -0
- data/src/pet/service_pet_get.tla +27 -0
- data/src/pet/service_pet_post.tla +78 -0
- data/src/pet/service_tag_post.tla +53 -0
- data/src/pet/service_tag_put.tla +82 -0
- data/src/pet/state +16 -0
- data/src/pet/state_infra.tla +6 -0
- data/src/pet/state_pet.tla +5 -0
- data/src/pet/state_tag_id.tla +2 -0
- data/src/pet/transaction +23 -0
- data/src/pet/transaction_delete_pet.tla +13 -0
- data/src/pet/transaction_enter_pet.tla +13 -0
- data/src/pet/transaction_enter_tag.tla +56 -0
- data/src/pet/transaction_error.tla +23 -0
- data/tla-sbuilder.gemspec +43 -0
- metadata +353 -0
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'mustache' # extendending implementation of
|
2
|
+
|
3
|
+
module Sbuilder
|
4
|
+
|
5
|
+
class Template < Mustache
|
6
|
+
|
7
|
+
include Sbuilder::Utils::MyLogger # mix logger
|
8
|
+
PROGNAME = "template" # progname for logger
|
9
|
+
|
10
|
+
|
11
|
+
# ------------------------------------------------------------------
|
12
|
+
# Attributes
|
13
|
+
|
14
|
+
# instance
|
15
|
+
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
|
+
# ------------------------------------------------------------------
|
23
|
+
# Constructor
|
24
|
+
|
25
|
+
def initialize( reader, options={} )
|
26
|
+
@logger = getLogger( PROGNAME, options )
|
27
|
+
@logger.info( "#{__method__} created" )
|
28
|
+
@logger.debug( "#{__method__}, options='#{options}" )
|
29
|
+
|
30
|
+
# init partial cache
|
31
|
+
@partials = {}
|
32
|
+
|
33
|
+
# inject reader
|
34
|
+
#@reader = Sbuilder::TemplateReader.new( options )
|
35
|
+
@reader = reader
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
# ------------------------------------------------------------------
|
40
|
+
# Services
|
41
|
+
|
42
|
+
def to_str( template_name, data )
|
43
|
+
@logger.info( "#{__method__}: template_name=#{template_name}" )
|
44
|
+
@logger.debug( "#{__method__}: template_name=#{template_name}" ) if @logger.debug?
|
45
|
+
# @logger.debug( "#{__method__}: nodes=#{data.nodes}" )
|
46
|
+
|
47
|
+
# data = add_dynamic_load( data )
|
48
|
+
|
49
|
+
@data = data
|
50
|
+
|
51
|
+
template = get_template( template_name )
|
52
|
+
# render( template, @data )
|
53
|
+
|
54
|
+
render( template, @data )
|
55
|
+
end
|
56
|
+
|
57
|
+
def render_str( template, data )
|
58
|
+
render( template, data )
|
59
|
+
end
|
60
|
+
|
61
|
+
# ------------------------------------------------------------------
|
62
|
+
# Integrate with mustache
|
63
|
+
|
64
|
+
# method used by mustache framework - delegate to 'get_partial'
|
65
|
+
def partial(name)
|
66
|
+
@logger.debug( "#{__method__} name=#{name}" )
|
67
|
+
|
68
|
+
return resolve_partial_direct(name[2..-1]) if name[0..1] == '!!'
|
69
|
+
get_partial( resolve_partial_name(name) )
|
70
|
+
end
|
71
|
+
|
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
|
86
|
+
def resolve_partial_name( name )
|
87
|
+
return name unless name[0..0] == '!'
|
88
|
+
# remove !, split, and use injected traves to access data
|
89
|
+
ret = @data.traverse( *(name[1..-1].split( "." )) )
|
90
|
+
if ret.nil?
|
91
|
+
raise <<-EOS
|
92
|
+
Could not resolve #{name} in template data
|
93
|
+
|
94
|
+
#{@data.to_yaml}
|
95
|
+
|
96
|
+
EOS
|
97
|
+
end
|
98
|
+
@logger.info( "#{__method__} name=#{name} --> #{ret}" )
|
99
|
+
ret
|
100
|
+
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
|
+
|
120
|
+
|
121
|
+
end # class
|
122
|
+
|
123
|
+
end # module
|
124
|
+
|
125
|
+
|
@@ -0,0 +1,206 @@
|
|
1
|
+
require 'mustache' # extendending implementation of
|
2
|
+
|
3
|
+
# ------------------------------------------------------------------
|
4
|
+
#
|
5
|
+
# Entry-poinsts
|
6
|
+
# - get_template
|
7
|
+
# - get_template_filepath
|
8
|
+
|
9
|
+
module Sbuilder
|
10
|
+
|
11
|
+
class TemplateReader
|
12
|
+
|
13
|
+
include Sbuilder::Utils::MyLogger # mix logger
|
14
|
+
PROGNAME = "treader" # progname for logger
|
15
|
+
|
16
|
+
|
17
|
+
# ------------------------------------------------------------------
|
18
|
+
# Attributes
|
19
|
+
|
20
|
+
# instance
|
21
|
+
attr_reader :template_paths # array of paths to search for templates
|
22
|
+
attr_writer :partials # f: partial-name --> template string
|
23
|
+
attr_writer :templates # f: template-name --> template string
|
24
|
+
|
25
|
+
# ------------------------------------------------------------------
|
26
|
+
# Constructor
|
27
|
+
|
28
|
+
def initialize( controller, options={} )
|
29
|
+
@logger = getLogger( PROGNAME, options )
|
30
|
+
@logger.info( "#{__method__} created, options='#{options}" )
|
31
|
+
|
32
|
+
# use default templates - prefix with user specified templates
|
33
|
+
@template_paths = options[:default_templates]
|
34
|
+
# for mustache templates
|
35
|
+
if options[:templates] then
|
36
|
+
@template_paths = options[:templates] + (options[:default_templates] || [] )
|
37
|
+
end
|
38
|
+
|
39
|
+
# # init partial cache
|
40
|
+
# @partials = {}
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
# ------------------------------------------------------------------
|
45
|
+
# Config - after contructor
|
46
|
+
|
47
|
+
# Null operation: no configuration actions taken. Maybe subclasses
|
48
|
+
# will implement something usefull
|
49
|
+
#
|
50
|
+
# @param steps [Hash] from 'model#templateData('steps')' with "steps"=>{'process', 'interface_name'}
|
51
|
+
# @param interfaces [Hash] from 'model#templateData('interfaces')' with "interface"=>{'interface_name', 'implementation'}
|
52
|
+
|
53
|
+
# def configSetup( steps, interfaces )
|
54
|
+
# @logger.info( "#{__method__} steps=#{steps["steps"].join('\n')}" )
|
55
|
+
# interfaces = interfaces["interfaces"] ? interfaces["interfaces"] : []
|
56
|
+
# @logger.info( "#{__method__} interfaces=#{interfaces.join('\n')}" )
|
57
|
+
# end
|
58
|
+
|
59
|
+
|
60
|
+
# ------------------------------------------------------------------
|
61
|
+
# filter actions
|
62
|
+
|
63
|
+
# default template when filtered
|
64
|
+
# @return [String] emptpy string for filtered templtae
|
65
|
+
def filtered_template
|
66
|
+
""
|
67
|
+
end
|
68
|
+
|
69
|
+
# To override in sub-classes
|
70
|
+
#
|
71
|
+
# @return [Boolean] true - show allways
|
72
|
+
def show_template( name )
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
# ------------------------------------------------------------------
|
79
|
+
# Services
|
80
|
+
|
81
|
+
# Check whether template 'name' should be be shown, next resolve
|
82
|
+
# location of a template file, and do 'File.read' on the file path
|
83
|
+
#
|
84
|
+
# @return [String] for template content
|
85
|
+
def get_template( name )
|
86
|
+
|
87
|
+
if !show_template( name )
|
88
|
+
@logger.info( "#{__method__} filtered, name=#{name}" )
|
89
|
+
return filtered_template
|
90
|
+
end
|
91
|
+
|
92
|
+
template_file = get_template_filepath( name )
|
93
|
+
@logger.info( "#{__method__} read template_file=#{template_file}" )
|
94
|
+
#File.read( template_file )
|
95
|
+
template_read( template_file )
|
96
|
+
|
97
|
+
end # get_template( name )
|
98
|
+
|
99
|
+
# @param path [String] path name to template
|
100
|
+
# @return [String] for template content
|
101
|
+
def template_read( path )
|
102
|
+
File.read( path )
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
# return path to an existing template file name
|
109
|
+
# @exception if template not found
|
110
|
+
def get_template_filepath( name )
|
111
|
+
|
112
|
+
@template_paths.each do |directory_or_gemname|
|
113
|
+
|
114
|
+
template_path = get_template_filepath_resolve( directory_or_gemname, name )
|
115
|
+
return template_path if template_path && File.exists?( template_path )
|
116
|
+
|
117
|
+
end # each
|
118
|
+
|
119
|
+
|
120
|
+
# could not find
|
121
|
+
|
122
|
+
raise <<-eos
|
123
|
+
|
124
|
+
No such template '#{name}' found in directories: #{@template_paths.join(", ")}
|
125
|
+
|
126
|
+
eos
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
# ------------------------------------------------------------------
|
131
|
+
# private
|
132
|
+
|
133
|
+
private
|
134
|
+
# return path to plain 'directory' or to gem directory
|
135
|
+
def get_template_filepath_resolve( directory_or_gemname, template_file )
|
136
|
+
@logger.info( "#{__method__} directory_or_gemname=#{directory_or_gemname}" )
|
137
|
+
if directory_or_gemname[-1] == '/' then
|
138
|
+
return get_template_filepath_in_directory( directory_or_gemname[0..-2], template_file )
|
139
|
+
else
|
140
|
+
directory = gemname_to_directory( directory_or_gemname )
|
141
|
+
return get_template_filepath_in_directory( directory, template_file )
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# return directory to 'gemspec'
|
146
|
+
def gemname_to_directory( gemname_and_spec )
|
147
|
+
|
148
|
+
# The version requirements are optional.
|
149
|
+
# You can also specify multiple version requirements, just append more at the end
|
150
|
+
gem_spec = gemname_and_spec.split(',')
|
151
|
+
gem_name, *gem_ver_reqs = gem_spec[0], gem_spec[1]
|
152
|
+
@logger.debug( "#{__method__}, gem_name=#{gem_name}, *gem_ver_reqs=#{gem_ver_reqs}" )
|
153
|
+
gdep = Gem::Dependency.new(gem_name, *gem_ver_reqs)
|
154
|
+
# find latest that satisifies
|
155
|
+
found_gspec = gdep.matching_specs.sort_by(&:version).last
|
156
|
+
@logger.debug( "#{__method__}, found_gspec=#{found_gspec}" )
|
157
|
+
# instead of using Gem::Dependency, you can also do:
|
158
|
+
# Gem::Specification.find_all_by_name(gem_name, *gem_ver_reqs)
|
159
|
+
|
160
|
+
if found_gspec
|
161
|
+
@logger.debug( "#{__method__}, Requirement '#{gdep}' already satisfied by #{found_gspec.name}-#{found_gspec.version}" )
|
162
|
+
template_path = "#{found_gspec.gem_dir}/mustache"
|
163
|
+
@logger.debug( "#{__method__}, template_path=#{template_path}" )
|
164
|
+
else
|
165
|
+
#puts "Requirement '#{gdep}' not satisfied; installing..."
|
166
|
+
# ver_args = gdep.requirements_list.map{|s| ['-v', s] }.flatten
|
167
|
+
# # multi-arg is safer, to avoid injection attacks
|
168
|
+
# system('gem', 'install', gem_name, *ver_args)
|
169
|
+
raise "Could not find gem '#{gdep}' - try 'gem install #{gdep}'"
|
170
|
+
end
|
171
|
+
|
172
|
+
return template_path
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
|
177
|
+
# return path to 'template_file' in an existing 'directory'
|
178
|
+
def get_template_filepath_in_directory( directory, template_file )
|
179
|
+
@logger.debug( "#{__method__} directory=#{directory}, template_file=#{template_file}" )
|
180
|
+
|
181
|
+
if ! File.exists?( directory ) then
|
182
|
+
@logger.info( "#{__method__} skipping directory #{directory} - it does not exist" )
|
183
|
+
return nil
|
184
|
+
end
|
185
|
+
|
186
|
+
if ! File.exists?( directory ) then
|
187
|
+
raise <<-eos
|
188
|
+
|
189
|
+
No such directory '#{directory}'.
|
190
|
+
|
191
|
+
eos
|
192
|
+
|
193
|
+
end
|
194
|
+
|
195
|
+
template_path = "#{directory}/#{template_file}"
|
196
|
+
@logger.info( "#{__method__} read template_path=#{template_path}" )
|
197
|
+
|
198
|
+
return template_path
|
199
|
+
|
200
|
+
end
|
201
|
+
|
202
|
+
end # class
|
203
|
+
|
204
|
+
end # module
|
205
|
+
|
206
|
+
|
@@ -0,0 +1,371 @@
|
|
1
|
+
require 'tla-parser-s' # TLA+ parser && resolver
|
2
|
+
|
3
|
+
module Sbuilder
|
4
|
+
|
5
|
+
|
6
|
+
# ------------------------------------------------------------------
|
7
|
+
# Use setup configuration to filter out part of reander templates.
|
8
|
+
#
|
9
|
+
# Implementation overrides 'whitelist' method in 'TemplateReader'.
|
10
|
+
# Uses 'TlaParserS::Resolver' to parse TLA+ snippets, and resolve
|
11
|
+
# modules to put in whitelist'
|
12
|
+
#
|
13
|
+
# Overview:
|
14
|
+
#
|
15
|
+
# - configSetup -methods receives 'steps' ie. array of interface
|
16
|
+
# names called in setup, and array of 'interfaces', which map
|
17
|
+
# interfaces to interface implementations
|
18
|
+
#
|
19
|
+
# - TlaParserS::Resolver#initSnippets parses tla-sbuilder code
|
20
|
+
# - repository
|
21
|
+
#
|
22
|
+
# - TlaParserS::Resolver#entryPoints resolves modules required to
|
23
|
+
# satisfy interface implementations used in setup
|
24
|
+
|
25
|
+
class TemplateContextReader < TemplateReader
|
26
|
+
|
27
|
+
extend Forwardable # for easy delegation
|
28
|
+
|
29
|
+
def_delegators :controller,
|
30
|
+
:getEntryPoints, # [String:Array] of
|
31
|
+
# implemenation names
|
32
|
+
# extracted from 'configSetup'
|
33
|
+
:getSetupPossibilities,
|
34
|
+
# [String:Array] names of
|
35
|
+
# possiblity operators defined
|
36
|
+
# for current setup
|
37
|
+
|
38
|
+
:isOptFilterSrc, # [Boolean] true when
|
39
|
+
# filtering
|
40
|
+
:output, # (level,msg) to output
|
41
|
+
:output_show, # (level)[Boolean] if show
|
42
|
+
:getModelNames # [String:Array] of names in model
|
43
|
+
|
44
|
+
# ------------------------------------------------------------------
|
45
|
+
# constructore
|
46
|
+
|
47
|
+
|
48
|
+
include Sbuilder::Utils::MyLogger # mix logger
|
49
|
+
PROGNAME = "creader" # progname for logger
|
50
|
+
|
51
|
+
# TLA+ standard library symbols
|
52
|
+
GLOBALS = %w( TRUE FALSE Cardinality)
|
53
|
+
|
54
|
+
# Sbuilder constant symbols
|
55
|
+
SBUILDER = %w( Nil InfrastructureServiceReturn InfrastructureServiceGetStatus
|
56
|
+
InfrastructureServiceGetResponse)
|
57
|
+
|
58
|
+
# these directories not unmustached
|
59
|
+
DOC_DIRS= [ "docs", "doc" ]
|
60
|
+
|
61
|
+
# ------------------------------------------------------------------
|
62
|
+
# Attributes
|
63
|
+
attr_reader :options # hash{:filter_list}
|
64
|
+
|
65
|
+
attr_reader :resolver # [TlaParserS::Resolver] to
|
66
|
+
# resolve entry point modules
|
67
|
+
|
68
|
+
|
69
|
+
attr_reader :controller # [Sbuilder::Controller]
|
70
|
+
|
71
|
+
|
72
|
+
attr_reader :setupName # currently generating
|
73
|
+
|
74
|
+
# ------------------------------------------------------------------
|
75
|
+
# Constructor
|
76
|
+
|
77
|
+
def initialize( controller, options={} )
|
78
|
+
super( controller, options )
|
79
|
+
@logger = getLogger( PROGNAME, options )
|
80
|
+
@logger.info( "#{__method__} created, options='#{options}" )
|
81
|
+
|
82
|
+
@controller = controller
|
83
|
+
|
84
|
+
@options = options
|
85
|
+
|
86
|
+
|
87
|
+
# # create '@resolver' && parse snippet repository
|
88
|
+
# if isOptFilterSrc then
|
89
|
+
# end
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
# ------------------------------------------------------------------
|
94
|
+
# Lazy intialize (so that configuration can take place)
|
95
|
+
def resolver
|
96
|
+
return @resolver if @resolver
|
97
|
+
|
98
|
+
raise "No option :cache_dir" unless options[:cache_dir] && !options[:cache_dir].empty?
|
99
|
+
unmustache_dir = "#{options[:cache_dir]}/unmustache"
|
100
|
+
|
101
|
+
# copy unmustached version for templates
|
102
|
+
unmustache( unmustache_dir )
|
103
|
+
|
104
|
+
# init resovelver using 'unmustache_dir'
|
105
|
+
@resolver = initResolver( unmustache_dir, options )
|
106
|
+
return @resolver
|
107
|
+
end
|
108
|
+
|
109
|
+
# ------------------------------------------------------------------
|
110
|
+
# Options
|
111
|
+
|
112
|
+
|
113
|
+
# @return [string] file path for filter list
|
114
|
+
def filter_list
|
115
|
+
options[:filter_list]
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
# ------------------------------------------------------------------
|
120
|
+
# config
|
121
|
+
|
122
|
+
def setSetupName( setupName )
|
123
|
+
@logger.info( "#{__method__} setupName=#{setupName}" )
|
124
|
+
@setupName = setupName
|
125
|
+
end
|
126
|
+
|
127
|
+
# ------------------------------------------------------------------
|
128
|
+
#
|
129
|
+
# Try to find a reason to show template
|
130
|
+
#
|
131
|
+
# @param [String] name of template to check @return [boolean] true
|
132
|
+
# when template should be shown normally, else false
|
133
|
+
#
|
134
|
+
# @return [Bool,String] show and text description
|
135
|
+
def show_template_do( name )
|
136
|
+
|
137
|
+
@logger.debug( "#{__method__}: check name=#{name}" )
|
138
|
+
|
139
|
+
# show all 'mustache templates'
|
140
|
+
return true, "mustache-template" if /.+\.mustache$/ =~ name
|
141
|
+
|
142
|
+
# show template witout extesions
|
143
|
+
return true, "no extension" if /^[^\/\.]*$/ =~ name
|
144
|
+
|
145
|
+
# show template if name is in whitelist 'opts[:filter_list]'
|
146
|
+
# puts "#{whitelist.join(',')}: '#{name}'--> #{whitelist.include?(name)}"
|
147
|
+
return true, "in whitelist" if whitelist.include?( name.to_s )
|
148
|
+
|
149
|
+
# (failed) there is no reason to show the template
|
150
|
+
return false, "default false"
|
151
|
+
end
|
152
|
+
|
153
|
+
# Overridden from super class. Wrapper around check actual check
|
154
|
+
# routine to simplify logging.
|
155
|
+
#
|
156
|
+
# @param [String] name of template to check
|
157
|
+
#
|
158
|
+
# @return [boolean] true when shown normally,else false
|
159
|
+
def show_template( name )
|
160
|
+
ret = show_template_do( name )
|
161
|
+
@logger.info( "#{__method__}: check show=#{name}-#{ret[1]} -> #{ret[0]}" )
|
162
|
+
ret[0]
|
163
|
+
end
|
164
|
+
|
165
|
+
# ------------------------------------------------------------------
|
166
|
+
# whitelist
|
167
|
+
|
168
|
+
# Return whitelisted template names.
|
169
|
+
#
|
170
|
+
# Implementation reads, and caches lines, in a file pointed by
|
171
|
+
# options[:filter_list]
|
172
|
+
#
|
173
|
+
# @return [Array] of whitelistes template names
|
174
|
+
def whitelist_file
|
175
|
+
return [] unless filter_list
|
176
|
+
File.readlines( filter_list ).each {|l| l.chomp! } || []
|
177
|
+
end
|
178
|
+
|
179
|
+
# Add Globals, Sbuilder and model symbols to resolver
|
180
|
+
#
|
181
|
+
#
|
182
|
+
def initResolverContext( resolver )
|
183
|
+
|
184
|
+
output( 1, " Initialize resolver context symbols" )
|
185
|
+
|
186
|
+
|
187
|
+
output( 2, " TLA+ symbols: #{GLOBALS.join( ',')}" )
|
188
|
+
output( 1, " #{GLOBALS.length} TLA+ symbols" )
|
189
|
+
resolver.initContext( GLOBALS )
|
190
|
+
|
191
|
+
output( 2, " Sbuilder symbols: #{SBUILDER.join( ',')}" )
|
192
|
+
output( 1, " #{SBUILDER.length} SBuilder symbols" )
|
193
|
+
resolver.initContext( SBUILDER )
|
194
|
+
|
195
|
+
model_names = getModelNames
|
196
|
+
output( 2, " Model symbols: #{model_names.join( ',')}" )
|
197
|
+
output( 1, " #{model_names.length} model symbols" )
|
198
|
+
resolver.initContext( model_names )
|
199
|
+
|
200
|
+
output( 1, " Initialize resolver context symbols - done" )
|
201
|
+
|
202
|
+
end
|
203
|
+
|
204
|
+
# Access controller to get information needed in un-mustache
|
205
|
+
# operation
|
206
|
+
def unmustache( unmustache_dir )
|
207
|
+
|
208
|
+
if ! Dir.exists?( unmustache_dir )
|
209
|
+
`mkdir #{unmustache_dir}`
|
210
|
+
exit unless $?.success?
|
211
|
+
end
|
212
|
+
|
213
|
+
unmustacheDo( controller.getCodeRepository, unmustache_dir, controller.getPreferencesData(setupName) )
|
214
|
+
end
|
215
|
+
|
216
|
+
# Unmustache files in 'src_dir' to 'target_dir'. Pass preferences
|
217
|
+
# json to mustache rendering
|
218
|
+
#
|
219
|
+
# @param src_dir [String] path source directory
|
220
|
+
# @param dest_dir [String] path destination directory
|
221
|
+
|
222
|
+
def unmustacheDo( src_dir, target_dir, preferences )
|
223
|
+
@logger.info( "#{__method__}, src_dir=#{src_dir}, target_dir=#{target_dir}, preferences=#{preferences}" )
|
224
|
+
|
225
|
+
output( 1, "Unmustache #{src_dir} --> #{target_dir} - start" )
|
226
|
+
|
227
|
+
source_files = Dir::glob( "#{src_dir}/**/*" )
|
228
|
+
source_files.each do |file|
|
229
|
+
|
230
|
+
next if File.directory?( file )
|
231
|
+
|
232
|
+
# extract relatve path in respect to src_dir
|
233
|
+
source = Pathname.new( File.expand_path( file) )
|
234
|
+
source_root = Pathname.new( File.expand_path( src_dir ) )
|
235
|
+
src = source.relative_path_from( source_root )
|
236
|
+
|
237
|
+
# do not unmustache anythins under docs, doc directory
|
238
|
+
if DOC_DIRS.include?( File.dirname( src ).split(File::SEPARATOR).first )
|
239
|
+
output( 1, " document file #{src} not unmustached" )
|
240
|
+
next
|
241
|
+
end
|
242
|
+
|
243
|
+
|
244
|
+
target = "#{target_dir}/#{src}"
|
245
|
+
# puts "#{source} --> #{target}"
|
246
|
+
|
247
|
+
if !File.exists?( File.dirname(target) )
|
248
|
+
cmd = "mkdir -p #{File.dirname(target)}"
|
249
|
+
output( 1, cmd )
|
250
|
+
`#{cmd}`
|
251
|
+
exit unless $?.success?
|
252
|
+
end # create dir
|
253
|
+
|
254
|
+
if !File.exists?(target) or (File.mtime( source ) > File.mtime(target))
|
255
|
+
cmd = "echo '#{preferences.to_json}' | mustache - #{source} > #{target}"
|
256
|
+
output( 2, " " + cmd )
|
257
|
+
`#{cmd}`
|
258
|
+
exit unless $?.success?
|
259
|
+
end # create file
|
260
|
+
end
|
261
|
+
|
262
|
+
output( 1, "Unmustache #{src_dir} --> #{target_dir} - done" )
|
263
|
+
|
264
|
+
|
265
|
+
end
|
266
|
+
|
267
|
+
|
268
|
+
|
269
|
+
# Create '@resolver' and initSnippets in 'snippet_repository'
|
270
|
+
#
|
271
|
+
# @param options [Hash] defining options for 'Resolver'
|
272
|
+
def initResolver( snippet_repository, options={} )
|
273
|
+
|
274
|
+
|
275
|
+
output( 1, "Parse snippet from repository #{snippet_repository} - start" )
|
276
|
+
|
277
|
+
cnt = 0
|
278
|
+
resolver = nil
|
279
|
+
Dir.chdir( snippet_repository ) do
|
280
|
+
|
281
|
+
@logger.info( "#{__method__}: init snippets in snippet_repository=#{snippet_repository}" )
|
282
|
+
snippet_files = Dir.glob( "**/*").map { |fileName| File.new(fileName)}
|
283
|
+
resolver = TlaParserS::Resolver.new( options )
|
284
|
+
|
285
|
+
# Add Globals, Sbuilder and model symbols to resolver
|
286
|
+
initResolverContext( resolver )
|
287
|
+
|
288
|
+
# Parse 'snippet_files' -
|
289
|
+
resolver.initSnippets( snippet_files ) do |stat,entry,e|
|
290
|
+
|
291
|
+
if stat
|
292
|
+
# success output dots no newline
|
293
|
+
output( 1, ".", false )
|
294
|
+
cnt += 1
|
295
|
+
true
|
296
|
+
else
|
297
|
+
|
298
|
+
# parses error
|
299
|
+
if filter_list
|
300
|
+
msg = <<-EOS
|
301
|
+
|
302
|
+
Parser error: option '--filter-list' set --> continue
|
303
|
+
#{e.message}
|
304
|
+
EOS
|
305
|
+
@logger.error( msg )
|
306
|
+
warn msg
|
307
|
+
true
|
308
|
+
else
|
309
|
+
msg = <<-EOS
|
310
|
+
Parser error: option '--filter-list' not set --> exiting
|
311
|
+
#{e.message}
|
312
|
+
EOS
|
313
|
+
@logger.error( msg )
|
314
|
+
warn msg
|
315
|
+
false
|
316
|
+
end # if filter_list
|
317
|
+
|
318
|
+
end # else - false: error
|
319
|
+
end # block
|
320
|
+
|
321
|
+
end # chdir
|
322
|
+
|
323
|
+
# start new line
|
324
|
+
output( 1, "" )
|
325
|
+
output( 1, "Parse snippet from repository #{snippet_repository} - done: parsed #{cnt} snippets" )
|
326
|
+
|
327
|
+
resolver
|
328
|
+
end
|
329
|
+
|
330
|
+
# Call resolver#resolveModule to find out the whitelist modules.
|
331
|
+
# Implementation uses 'entry_points' configured in 'configSetup'
|
332
|
+
#
|
333
|
+
# @return [String:Array] of white listed modules
|
334
|
+
def whitelist_resolved
|
335
|
+
rslv = resolver
|
336
|
+
output( 1, "Resolving symbols - start" )
|
337
|
+
entrypoints = getEntryPoints + getSetupPossibilities
|
338
|
+
@logger.debug("#{__method__}: entrypoints=#{entrypoints}")
|
339
|
+
ret = rslv.resolveModules( entrypoints ) do |type,arr|
|
340
|
+
case type
|
341
|
+
when "unresolved"
|
342
|
+
# defult to output unresolved - if some unresolved symbols
|
343
|
+
output( arr.any? ? 1 : 2, " #{type} : [#{arr.join(',')}]" )
|
344
|
+
output( 1, " #{type} : count #{arr.length}" )
|
345
|
+
else
|
346
|
+
output( 2, " #{type} : [#{arr.join(',')}]" )
|
347
|
+
output( 1, " #{type} : count #{arr.length} #{ !output_show( 2 ) ? '(add verbosity to show list)' : '' }" )
|
348
|
+
end
|
349
|
+
end
|
350
|
+
output( 1, "Resolving symbols - done" )
|
351
|
+
return ret
|
352
|
+
end
|
353
|
+
|
354
|
+
|
355
|
+
# Return whitelisted template names.
|
356
|
+
#
|
357
|
+
#
|
358
|
+
# @return [Array] of whitelistes template names
|
359
|
+
|
360
|
+
def whitelist
|
361
|
+
return @whitelist if @whitelist
|
362
|
+
@whitelist = whitelist_file + whitelist_resolved
|
363
|
+
@logger.info( "#{__method__}, whitelist=#{@whitelist}" )
|
364
|
+
@whitelist
|
365
|
+
end
|
366
|
+
|
367
|
+
private
|
368
|
+
|
369
|
+
|
370
|
+
end
|
371
|
+
end
|