tla-sbuilder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (210) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +328 -0
  3. data/VERSION +1 -0
  4. data/bin/sbuilder.rb +5 -0
  5. data/lib/cli/cli-customer.rb +420 -0
  6. data/lib/cli/cli-example.rb +92 -0
  7. data/lib/cli/cli-pet.rb +767 -0
  8. data/lib/cli/cli-text.rb +226 -0
  9. data/lib/cli/cli.rb +298 -0
  10. data/lib/sbuilder.rb +52 -0
  11. data/lib/sbuilder/constants.rb +72 -0
  12. data/lib/sbuilder/controller.rb +798 -0
  13. data/lib/sbuilder/default-sbuilder.yaml +372 -0
  14. data/lib/sbuilder/domain.rb +124 -0
  15. data/lib/sbuilder/domain_cardinality.rb +37 -0
  16. data/lib/sbuilder/domain_value.rb +81 -0
  17. data/lib/sbuilder/exception.rb +27 -0
  18. data/lib/sbuilder/extension_loader.rb +721 -0
  19. data/lib/sbuilder/factory.rb +234 -0
  20. data/lib/sbuilder/model.rb +356 -0
  21. data/lib/sbuilder/mustache/template.rb +125 -0
  22. data/lib/sbuilder/mustache/template_reader.rb +206 -0
  23. data/lib/sbuilder/mustache/template_reader_context.rb +371 -0
  24. data/lib/sbuilder/param_set.rb +132 -0
  25. data/lib/sbuilder/param_set_db.rb +20 -0
  26. data/lib/sbuilder/param_set_def.rb +57 -0
  27. data/lib/sbuilder/param_set_if.rb +68 -0
  28. data/lib/sbuilder/param_set_loader.rb +77 -0
  29. data/lib/sbuilder/param_set_loader_swagger.rb +424 -0
  30. data/lib/sbuilder/param_set_step.rb +62 -0
  31. data/lib/sbuilder/param_sets.rb +54 -0
  32. data/lib/sbuilder/parameter.rb +97 -0
  33. data/lib/sbuilder/parameter_container.rb +72 -0
  34. data/lib/sbuilder/parameter_dom.rb +70 -0
  35. data/lib/sbuilder/parameter_ref.rb +71 -0
  36. data/lib/sbuilder/resolver.rb +78 -0
  37. data/lib/sbuilder/resolver_loader.rb +79 -0
  38. data/lib/sbuilder/resolver_loader_yaml.rb +103 -0
  39. data/lib/sbuilder/resolver_rule.rb +36 -0
  40. data/lib/sbuilder/resolver_rule_match.rb +55 -0
  41. data/lib/sbuilder/resolver_rule_ref.rb +37 -0
  42. data/lib/utils/hash_inject.rb +12 -0
  43. data/lib/utils/logger.rb +80 -0
  44. data/lib/utils/netio.rb +58 -0
  45. data/lib/utils/string_inject.rb +10 -0
  46. data/lib/utils/version.rb +13 -0
  47. data/mustache/cfg/const_def.mustache +8 -0
  48. data/mustache/cfg/const_run.mustache +3 -0
  49. data/mustache/cfg/invariant-infrastructure-service.mustache +4 -0
  50. data/mustache/cfg/macro_run.mustache +6 -0
  51. data/mustache/cfg/module_footer.mustache +0 -0
  52. data/mustache/cfg/module_header.mustache +7 -0
  53. data/mustache/data-model-dump.mustache +19 -0
  54. data/mustache/data-model-footer.mustache +5 -0
  55. data/mustache/data-model-header.mustache +16 -0
  56. data/mustache/definition_types.mustache +40 -0
  57. data/mustache/domains.mustache +20 -0
  58. data/mustache/domains_assign.mustache +22 -0
  59. data/mustache/domains_run.mustache +21 -0
  60. data/mustache/extend/extend_assumptions.mustache +7 -0
  61. data/mustache/extend/extend_const.mustache +5 -0
  62. data/mustache/extend/extend_implementation.mustache +9 -0
  63. data/mustache/extend/extend_invariant.mustache +7 -0
  64. data/mustache/extend/extend_invariant_cfg.mustache +7 -0
  65. data/mustache/extend/extend_macros.mustache +19 -0
  66. data/mustache/extend/extend_operations.mustache +9 -0
  67. data/mustache/extend/extend_state.mustache +9 -0
  68. data/mustache/infrastructure-service-init.mustache +36 -0
  69. data/mustache/infrastructure-service-variables.mustache +10 -0
  70. data/mustache/interface_processes.mustache +38 -0
  71. data/mustache/interface_stubs_dummy.mustache +13 -0
  72. data/mustache/interface_types.mustache +52 -0
  73. data/mustache/markdown-header.mustache +24 -0
  74. data/mustache/markdown-toc.mustache +13 -0
  75. data/mustache/name_definition_type.mustache +5 -0
  76. data/mustache/name_domain.mustache +5 -0
  77. data/mustache/name_domain_value.mustache +5 -0
  78. data/mustache/name_domain_value_prefix.mustache +5 -0
  79. data/mustache/name_interface_response_type.mustache +6 -0
  80. data/mustache/name_interface_type.mustache +6 -0
  81. data/mustache/name_parameter_definition.mustache +5 -0
  82. data/mustache/name_parameter_type.mustache +6 -0
  83. data/mustache/name_process.mustache +6 -0
  84. data/mustache/name_type_invariant.mustache +5 -0
  85. data/mustache/name_variable.mustache +6 -0
  86. data/mustache/operator-infrastructure-service.mustache +13 -0
  87. data/mustache/possibility/module_extends.mustache +1 -0
  88. data/mustache/possibility/module_footer.mustache +1 -0
  89. data/mustache/possibility/module_header.mustache +8 -0
  90. data/mustache/possibility/possibility_definition.mustache +12 -0
  91. data/mustache/possibility/possibility_directive.mustache +1 -0
  92. data/mustache/possibility/possility_setup.mustache +28 -0
  93. data/mustache/setup/module_footer.mustache +1 -0
  94. data/mustache/setup/module_header.mustache +9 -0
  95. data/mustache/setup/operator_run.mustache +7 -0
  96. data/mustache/setup/operator_tick.mustache +2 -0
  97. data/mustache/setup/steps_run.mustache +22 -0
  98. data/mustache/setup/steps_run_bind_rule.mustache +51 -0
  99. data/mustache/setup/steps_run_bind_set.mustache +37 -0
  100. data/mustache/setup/steps_run_parameterBind.mustache +80 -0
  101. data/mustache/setup/steps_run_parameterExact.mustache +79 -0
  102. data/mustache/state_type_invariant-infrastructure-service.mustache +49 -0
  103. data/mustache/state_type_invariant.mustache +17 -0
  104. data/mustache/state_type_invariant_cfg.mustache +18 -0
  105. data/mustache/state_variables.mustache +20 -0
  106. data/mustache/tla/const_def.mustache +5 -0
  107. data/mustache/tla/const_run.mustache +3 -0
  108. data/mustache/tla/macro-infrastructure-service.mustache +14 -0
  109. data/mustache/tla/macro_run.mustache +40 -0
  110. data/mustache/tla/module_footer.mustache +2 -0
  111. data/mustache/tla/module_header.mustache +9 -0
  112. data/mustache/tla/operator_run.mustache +8 -0
  113. data/mustache/tla/operators-infrastructure-service.mustache +12 -0
  114. data/mustache/tla/plc_define_footer.mustache +1 -0
  115. data/mustache/tla/plc_define_header.mustache +1 -0
  116. data/mustache/tla/plc_define_run.mustache +59 -0
  117. data/mustache/tla/plc_footer.mustache +2 -0
  118. data/mustache/tla/plc_header.mustache +2 -0
  119. data/mustache/tla/plc_run_state.mustache +12 -0
  120. data/mustache/tla/plc_tail.mustache +8 -0
  121. data/mustache/tla/plc_translation.mustache +2 -0
  122. data/resources/schema/json_schema/draft-04.json +150 -0
  123. data/resources/schema/swagger/2.0/schema.json +1591 -0
  124. data/src-extend/README +2 -0
  125. data/src-extend/extend/extend_assumptions.mustache +7 -0
  126. data/src-extend/extend/extend_const.mustache +5 -0
  127. data/src-extend/extend/extend_implementation.mustache +9 -0
  128. data/src-extend/extend/extend_invariant.mustache +11 -0
  129. data/src-extend/extend/extend_invariant_cfg.mustache +7 -0
  130. data/src-extend/extend/extend_macros.mustache +19 -0
  131. data/src-extend/extend/extend_operations.mustache +9 -0
  132. data/src-extend/extend/extend_state.mustache +9 -0
  133. data/src-extend/extend_app/assumption +20 -0
  134. data/src-extend/extend_app/correctness +19 -0
  135. data/src-extend/extend_app/correctness.cfg +9 -0
  136. data/src-extend/extend_app/infrastructure +25 -0
  137. data/src-extend/extend_app/interface +11 -0
  138. data/src-extend/extend_app/operator +18 -0
  139. data/src-extend/extend_app/possibility +16 -0
  140. data/src-extend/extend_app/service +33 -0
  141. data/src-extend/extend_app/state +16 -0
  142. data/src-extend/extend_app/transaction +22 -0
  143. data/src/pet/assumption +29 -0
  144. data/src/pet/assumption_address_domains.tla +12 -0
  145. data/src/pet/assumption_domains.tla +16 -0
  146. data/src/pet/assumption_generic.tla +8 -0
  147. data/src/pet/assumption_id_domains.tla +2 -0
  148. data/src/pet/assumption_owner_domains.tla +14 -0
  149. data/src/pet/assumption_pet_domains.tla +16 -0
  150. data/src/pet/assumption_tag_domains.tla +13 -0
  151. data/src/pet/correctness +24 -0
  152. data/src/pet/correctness.cfg +9 -0
  153. data/src/pet/correctness_coherent_owner_address.tla +6 -0
  154. data/src/pet/correctness_pet_name.tla +4 -0
  155. data/src/pet/correctness_ref_tag.tla +13 -0
  156. data/src/pet/correctness_type_invariants.tla +12 -0
  157. data/src/pet/correctness_unique_pet.tla +3 -0
  158. data/src/pet/correctness_unique_tag.tla +3 -0
  159. data/src/pet/docs/Petstore.md +117 -0
  160. data/src/pet/extend/extend_assumptions.mustache +7 -0
  161. data/src/pet/extend/extend_implementation.mustache +9 -0
  162. data/src/pet/extend/extend_invariant.mustache +11 -0
  163. data/src/pet/extend/extend_invariant_cfg.mustache +7 -0
  164. data/src/pet/extend/extend_macros.mustache +19 -0
  165. data/src/pet/extend/extend_operations.mustache +9 -0
  166. data/src/pet/extend/extend_state.mustache +9 -0
  167. data/src/pet/infrastructure +25 -0
  168. data/src/pet/infrastructure_id_get.tla +24 -0
  169. data/src/pet/interface +12 -0
  170. data/src/pet/interface_delete_pet.tla +5 -0
  171. data/src/pet/interface_get_pet.tla +4 -0
  172. data/src/pet/interface_post_pet.tla +5 -0
  173. data/src/pet/interface_post_tag.tla +5 -0
  174. data/src/pet/interface_put_tag.tla +3 -0
  175. data/src/pet/operator +30 -0
  176. data/src/pet/operator_find_tag_by_owner_name.tla +1 -0
  177. data/src/pet/operator_get_pet.tla +4 -0
  178. data/src/pet/operator_get_pet_by_tag.tla +4 -0
  179. data/src/pet/operator_get_tag.tla +10 -0
  180. data/src/pet/operator_new_owner.tla +3 -0
  181. data/src/pet/operator_new_pet.tla +13 -0
  182. data/src/pet/operator_new_tag.tla +3 -0
  183. data/src/pet/operator_next_pet_id.tla +3 -0
  184. data/src/pet/operator_responses.tla +8 -0
  185. data/src/pet/operator_tag_exists.tla +2 -0
  186. data/src/pet/operator_tag_owner_validated.tla +2 -0
  187. data/src/pet/operator_tag_referenced.tla +4 -0
  188. data/src/pet/operator_valid_owner.tla +17 -0
  189. data/src/pet/operator_valid_pet.tla +6 -0
  190. data/src/pet/operator_valid_tag.tla +5 -0
  191. data/src/pet/possibility +18 -0
  192. data/src/pet/possibility_at_least_two_tags.tla +12 -0
  193. data/src/pet/possibility_invalid_tag_address.tla +8 -0
  194. data/src/pet/service +35 -0
  195. data/src/pet/service_pet_delete.tla +11 -0
  196. data/src/pet/service_pet_get.tla +27 -0
  197. data/src/pet/service_pet_post.tla +78 -0
  198. data/src/pet/service_tag_post.tla +53 -0
  199. data/src/pet/service_tag_put.tla +82 -0
  200. data/src/pet/state +16 -0
  201. data/src/pet/state_infra.tla +6 -0
  202. data/src/pet/state_pet.tla +5 -0
  203. data/src/pet/state_tag_id.tla +2 -0
  204. data/src/pet/transaction +23 -0
  205. data/src/pet/transaction_delete_pet.tla +13 -0
  206. data/src/pet/transaction_enter_pet.tla +13 -0
  207. data/src/pet/transaction_enter_tag.tla +56 -0
  208. data/src/pet/transaction_error.tla +23 -0
  209. data/tla-sbuilder.gemspec +43 -0
  210. 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