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,132 @@
1
+
2
+ module Sbuilder
3
+
4
+ class ParamSet
5
+
6
+ attr_reader :parameters # array of parameters:Parameter
7
+
8
+ # ------------------------------------------------------------------
9
+ # mixer
10
+ PROGNAME = "ParamSet" # progname for logger
11
+ include Sbuilder::Utils::MyLogger # mix logger
12
+
13
+
14
+ # ------------------------------------------------------------------
15
+ # constrcutore
16
+ def initialize( options = {} )
17
+ @logger = getLogger( PROGNAME, options )
18
+ @logger.info( "#{__method__} initialized" )
19
+ @parameters = []
20
+ end
21
+
22
+ def to_s
23
+ "#{getId}"
24
+ end
25
+
26
+ # normally resolve 'parameter' sub-classes may override
27
+ def parametersToResolve
28
+ parameters
29
+ end
30
+
31
+ # ------------------------------------------------------------------
32
+ # builder
33
+ def addParameter( param )
34
+ parameters << param
35
+ self
36
+ end
37
+
38
+ # ------------------------------------------------------------------
39
+ # identifier for finding domain matche
40
+
41
+ def matchesWithParamSet( matcher )
42
+ matcher.is_a?( String ) ? getId == matcher : (getId =~ matcher) != nil
43
+ end
44
+
45
+ def getId
46
+ doGetId
47
+ end
48
+
49
+
50
+ def doGetId
51
+ msg = "Sub class should implement doGetId -method"
52
+ @logger.error( "#{__method__} #{msg}" )
53
+ raise NoMethodError.new( msg )
54
+ end
55
+
56
+ # ------------------------------------------------------------------
57
+ # generata phase
58
+
59
+
60
+ # return hash for generation phase, false if no paramteers
61
+ def parameter_definitions( model )
62
+ arra = parameters.map.with_index do |p,i|
63
+ # puts "p=#{p}"
64
+ parameter_def = p.parameter_definition( model )
65
+ # puts "parameter_def=#{parameter_def}"
66
+ parameter_def[:parameter_name] = ParamSet.cleanUpName( parameter_def[:parameter_name] )
67
+
68
+ parameter_def[:_comma] = (i < parameters.length-1 ? "," : "" ) # empty string for last element
69
+ parameter_def
70
+ # {
71
+ # :name => p.name,
72
+ # :parameter_name => ParamSet.cleanUpName( p.name ),
73
+ # :type => p.getType,
74
+ # :
75
+ # }
76
+ end
77
+ # return false if no parameter
78
+ return false if arra.length == 0
79
+ return arra
80
+ end
81
+
82
+ # make it valid identifier
83
+ def self.cleanUpName( name )
84
+ return name ?
85
+ name.gsub( /\./, "_" ) : # . --> _
86
+ name
87
+ end
88
+
89
+ # getId with invalid-caharacters as underscpce
90
+ def getName
91
+ return getId.
92
+ gsub( /\//, "_" ). # / --> _
93
+ gsub( /\(/, "_" ). # ( --> _
94
+ gsub( /\{/, "_" ). # { --> _
95
+ gsub( /\}/, "_" ). # } --> _
96
+ gsub( /\)/, "_" ) # ) --> _
97
+
98
+ end
99
+
100
+ # ------------------------------------------------------------------
101
+ # locateParameter
102
+
103
+ # Locate parameter 'key', raise on an error if not found
104
+ def locateParameter( key )
105
+ key = key.first if key.is_a?( Array )
106
+ @logger.debug( "#{__method__} key=#{key}" )
107
+
108
+
109
+ # locate key in this paramter set
110
+ # puts "parameters=#{parameters}"
111
+ found = parameters.select do |parameter|
112
+ # puts "parameter.name #{parameter.name} == key = #{key}"
113
+ parameter.name == key
114
+ end.first
115
+ @logger.debug( "#{__method__} key=#{key} --> found='#{found}' found.class=#{found.class}" )
116
+ raise <<-EOS if found.nil?
117
+
118
+ Could not locate parameter '#{key}' in parameter set '#{getId}'
119
+
120
+ Valid names in parameter set '#{getId}': #{parameters.map {|parameter| parameter.name}.join(',')}
121
+
122
+ EOS
123
+
124
+ return found
125
+
126
+ end
127
+
128
+
129
+
130
+ end # class
131
+
132
+ end
@@ -0,0 +1,20 @@
1
+
2
+ module Sbuilder
3
+
4
+ class ParamSet_Db < ParamSet
5
+
6
+ # ------------------------------------------------------------------
7
+ # mixer
8
+ PROGNAME = "ParamSet_Db" # progname for logger
9
+ include Sbuilder::Utils::MyLogger # mix logger
10
+
11
+ # ------------------------------------------------------------------
12
+ # constrcutore
13
+ def initialize( options = {} )
14
+ @logger = getLogger( PROGNAME, options )
15
+ @logger.info( "#{__method__} initialized" )
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,57 @@
1
+
2
+ module Sbuilder
3
+
4
+ # interface paramter set (identified by path+operations)
5
+ class ParamSetDef < ParamSet
6
+
7
+ attr_reader :isArray # defaults 'false'
8
+ attr_reader :definition # REST path
9
+
10
+
11
+ # ------------------------------------------------------------------
12
+ # mixer
13
+ PROGNAME = "ParamSet_Def" # progname for logger
14
+ include Sbuilder::Utils::MyLogger # mix logger
15
+
16
+ # ------------------------------------------------------------------
17
+ # constrcutore
18
+ def initialize( options = {} )
19
+ super( options )
20
+ @logger = getLogger( PROGNAME, options )
21
+ @logger.info( "#{__method__} initialized" )
22
+
23
+ # default is not an arrays
24
+ @isArray = false
25
+ end
26
+
27
+
28
+ # ------------------------------------------------------------------
29
+ # setIdentity
30
+
31
+ # set configure
32
+ def setDefinition( definition )
33
+ @definition = definition
34
+ self
35
+ end
36
+
37
+ # ------------------------------------------------------------------
38
+ # implentation
39
+
40
+ # return identity
41
+ def doGetId
42
+ "#{definition}"
43
+ end
44
+
45
+
46
+ # ------------------------------------------------------------------
47
+ #
48
+ def setIsArray( isArray = true )
49
+ @isArray = isArray
50
+ self
51
+ end
52
+
53
+
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,68 @@
1
+
2
+ module Sbuilder
3
+
4
+ # interface paramter set (identified by path+operations)
5
+ class ParamSet_If < ParamSet
6
+
7
+ attr_reader :path # REST path
8
+ attr_reader :operation # REST path
9
+ attr_reader :response # returned from interface
10
+ attr_reader :infrastructureService # default 'false'
11
+
12
+ # ------------------------------------------------------------------
13
+ # mixer
14
+ PROGNAME = "ParamSet_If" # progname for logger
15
+ include Sbuilder::Utils::MyLogger # mix logger
16
+
17
+ # ------------------------------------------------------------------
18
+ # constrcutore
19
+ def initialize( options = {} )
20
+ super( options )
21
+ @logger = getLogger( PROGNAME, options )
22
+ @logger.info( "#{__method__} initialized" )
23
+ @response = nil
24
+ @infrastructureService = false
25
+ end
26
+
27
+ # # normally resolve 'parameter', however in my case resolve also responses
28
+ # def parametersToResolve
29
+ # return parameters + ( @response ? @response.parameters : [])
30
+ # end
31
+
32
+
33
+ # ------------------------------------------------------------------
34
+ # configure
35
+
36
+ # def addResponse( response )
37
+ # @responses << response
38
+ # self
39
+ # end
40
+
41
+ def setResponse( response )
42
+ @response = response
43
+ self
44
+ end
45
+
46
+ def setInfrastructureService( infrastructureService )
47
+ @infrastructureService = infrastructureService
48
+ self
49
+ end
50
+
51
+ # ------------------------------------------------------------------
52
+ # setIdentity
53
+
54
+ # set identity
55
+ def setIdentity( path, operation )
56
+ @path = path
57
+ @operation = operation
58
+ self
59
+ end
60
+
61
+ # return identity
62
+ def doGetId
63
+ "#{path}(#{operation})"
64
+ end
65
+
66
+ end
67
+
68
+ end
@@ -0,0 +1,77 @@
1
+
2
+ module Sbuilder
3
+
4
+ class ParamSetLoader
5
+
6
+ attr_reader :factory # to create stuff
7
+ attr_accessor :controller # get sets when load starts
8
+
9
+ # ------------------------------------------------------------------
10
+ # mixer
11
+ PROGNAME = "ParamSetLoader" # progname for logger
12
+ include Sbuilder::Utils::MyLogger # mix logger
13
+
14
+
15
+ # ------------------------------------------------------------------
16
+ # constructore
17
+
18
+ def initialize( factory, options = {} )
19
+ @logger = getLogger( PROGNAME, options )
20
+ @logger.info( "#{__method__} initialized" )
21
+ @factory = factory
22
+ end
23
+
24
+ # @param loaderDef [Hash] adding configuration for loader (override)
25
+ def configure( loaderDef )
26
+ doConfigure( loaderDef )
27
+ end
28
+
29
+ def doConfigure( loaderDef )
30
+ msg = "Sub class should implement doConfigure -method"
31
+ @logger.error( "#{__method__} #{msg}" )
32
+ raise NoMethodError.new( msg )
33
+ end
34
+
35
+ # ------------------------------------------------------------------
36
+ # load paramset from 'fileUri'
37
+ def load( controller, fileUri, cacheFile=nil )
38
+ # controller which control loading
39
+ @controller = controller
40
+
41
+ begin
42
+ loaded = doLoad( fileUri, cacheFile )
43
+ rescue Exception => e
44
+ msg = "Exception '#{e}' when loading fileUri '#{fileUri}'"
45
+ @logger.error( "#{__method__} #{msg}" )
46
+ puts msg
47
+ raise e
48
+ end
49
+
50
+ # # iterate && report to controller
51
+ # loaded.each do |paramSet|
52
+ # controller.interfaceEncountered( paramSet )
53
+ # end
54
+ end
55
+
56
+ def createParamSet( type )
57
+ factory.createParamSet( type )
58
+ end
59
+
60
+ def createParameter( type )
61
+ factory.createParameter( type )
62
+ end
63
+
64
+
65
+ # ------------------------------------------------------------------
66
+ # sub-class should implement the doload method
67
+ def doLoad( fileUri, cacheFile=nil )
68
+ msg = "Sub class should implement doLoad -method"
69
+ @logger.error( "#{__method__} #{msg}" )
70
+ raise NoMethodError.new( msg )
71
+ end
72
+
73
+
74
+ end # class ParamSetLoader
75
+
76
+
77
+ end # module
@@ -0,0 +1,424 @@
1
+ # coding: utf-8
2
+ require 'yaml'
3
+ require 'json'
4
+ require 'hashie'
5
+
6
+ require 'json-schema'
7
+
8
+ module Sbuilder
9
+
10
+
11
+
12
+ class ParamSetLoaderSwagger < ParamSetLoader
13
+
14
+ attr_reader :infrastructureServices # default 'false'
15
+
16
+ # ------------------------------------------------------------------
17
+ # mixer
18
+ PROGNAME = "LoadSwagger" # progname for logger
19
+ include Sbuilder::Utils::MyLogger # mix logger
20
+
21
+ # ------------------------------------------------------------------
22
+ # constrcutore
23
+ def initialize( factory, options = {} )
24
+ super( factory, options )
25
+ @logger = getLogger( PROGNAME, options )
26
+ @logger.info( "#{__method__} initialized" )
27
+
28
+ # properties
29
+ @infrastructureServices = false
30
+
31
+ end
32
+
33
+ # extract 'intfractureServices' property from 'paramsetLoaderDef'
34
+ #
35
+ # @param paramsetLoaderDef [Hash] configuration in 'sbuilder.yaml'
36
+ #
37
+ def doConfigure( paramsetLoaderDef )
38
+ @infrastructureServices = true if paramsetLoaderDef['infrastructureServices']
39
+ end
40
+
41
+
42
+ # implements abstract super class method validates, loads
43
+ # interfaces and definitions in YAML parsed from 'yamlFileUri'
44
+
45
+ # @param yamlFileUri [String] path or url to YAML file to process
46
+
47
+ def doLoad( yamlFileUri, cacheFile=nil )
48
+ @logger.info( "#{__method__} yamlFileUri=#{yamlFileUri}" )
49
+ # swagger_hash = YAML.load_file( yamlFileUri )
50
+ yaml_lines = Sbuilder::Utils::NetIo.read_lines_cached( yamlFileUri, cacheFile )
51
+ # puts yaml_lines
52
+ # puts "yamlFileUri=#{yamlFileUri}"
53
+ swagger_hash = YAML.load( yaml_lines )
54
+
55
+ validate( swagger_hash )
56
+ doLoadInterfaces( swagger_hash )
57
+ doLoadDefinitions( swagger_hash )
58
+
59
+ end
60
+
61
+ # ==================================================================
62
+ # entry points
63
+
64
+ # calls '@controller.definitionEncountered' for each parameter set
65
+ # found in swagger configuration
66
+ # @param swagger_hash [swagger 2.0]
67
+
68
+ def doLoadDefinitions( swagger_hash )
69
+ paramsSets = swaggerDefinitionParamsets( swagger_hash )
70
+ paramsSets.each do |paramSet|
71
+ controller.definitionEncountered( paramSet )
72
+ end
73
+
74
+ end
75
+
76
+ # calls '@controller.interfaceEncountered' for each parameter set
77
+ # found in swagger configuration
78
+ #
79
+ # @param swagger_hash [swagger 2.0]
80
+
81
+ def doLoadInterfaces( swagger_hash )
82
+
83
+ interface_paramsSets = swaggerPathInterfaces( swagger_hash )
84
+ @logger.info( "#{__method__} loaded=#{interface_paramsSets.length} interface_paramsSets" )
85
+
86
+ interface_paramsSets.each do |interface|
87
+ controller.interfaceEncountered( interface )
88
+ end
89
+
90
+ end
91
+
92
+ # entry poinsts
93
+ # ==================================================================
94
+
95
+ # Validates this object against the Swagger specification and
96
+ # returns the first detected error. Faster than
97
+ # {#fully_validate}.
98
+ #
99
+ # @return [true] if the object fully complies with the Swagger specification.
100
+ # @raise [Swagger::InvalidDefinition] if an error is found.
101
+ def validate( json )
102
+ JSON::Validator.validate!(swagger_schema, json ) #
103
+ # JSON::Validator.fully_validate(swagger_schema, json ) #
104
+ rescue JSON::Schema::ValidationError => e
105
+ raise Sbuilder::LoaderException.new, e.message
106
+ end
107
+
108
+
109
+ private def swagger_schema
110
+ @swagger_schema ||= JSON.parse(File.read(Sbuilder::Constants::SWAGGER_SCHEMA))
111
+ # FIXME: Swagger should be able to parse offline. Blocked by json-schema.
112
+ # Offline workaround
113
+ # @swagger_schema = JSON.parse(File.read(SWAGGER_SCHEMA)
114
+ # .gsub('http://json-schema.org/draft-04/schema', "file://#{SWAGGER_SCHEMA}"))
115
+ # @swagger_schema['$schema'] = 'http://json-schema.org/draft-04/schema#'
116
+ # @swagger_schema
117
+ end
118
+
119
+
120
+ private
121
+
122
+ # ------------------------------------------------------------------
123
+ # iterate defitions
124
+ def swaggerDefinitionParamsets( swagger_hash )
125
+ paramSets = []
126
+ swagger_hash['definitions'] && swagger_hash['definitions'].each do |defineKey,definedDoc|
127
+ # puts "defineKey=#{defineKey} -> #{definedDoc}"
128
+
129
+ # create set && configure param set for a defintion
130
+ paramSet = createParamSet( Sbuilder::Constants::SWAGGER_DEFINITION )
131
+ paramSet.setDefinition( defineKey )
132
+ paramSet.setIsArray if definedDoc['type'] == 'array'
133
+ paramSets << paramSet
134
+
135
+ if hasRef( definedDoc ) then
136
+ # case paramter set is a wrapper - most likely an array
137
+ reference_parameter( paramSet, defineKey, getRefDocumentName( definedDoc ), definedDoc['type'] )
138
+ else
139
+
140
+ expandedDocs = expand_definedDocs( definedDoc, swagger_hash )
141
+ # puts " defineKey=#{defineKey} --> expandedDocs=#{expandedDocs}"
142
+
143
+ # iterate array of [ { <name> = { "type"=>.., <format> =>..}, <name> => ..}, ... ]
144
+ expandedDocs.each do |expandedDoc|
145
+ # puts "#----->{op}-expandedDoc->#{expandedDoc}"
146
+ expandedDoc.each do |parameterName,parameterProps|
147
+ @logger.debug( "#{__method__} {op}-parameterName->#{parameterName}, parameterProps=>#{parameterProps}" )
148
+ if hasRef( parameterProps ) then
149
+ reference_parameter( paramSet, parameterName, getRefDocumentName( parameterProps ), parameterProps['type'] )
150
+ else
151
+ simple_parameter( paramSet, parameterName, parameterProps['type'] )
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ end # each definitions
158
+
159
+ return paramSets
160
+ end
161
+
162
+ # ------------------------------------------------------------------
163
+ # iterate interface ['path'][<operation>]['paramters']
164
+
165
+ def swaggerPathInterfaces( swagger_hash )
166
+
167
+ @logger.info( "#{__method__} starting" )
168
+
169
+ # collect all interface paramsets together
170
+ paramSets = []
171
+
172
+ # interfaces are hashes under 'paths'/<path>/<op>
173
+ swagger_hash['paths'].each do |path,ops|
174
+ ops.each do |op,opdef|
175
+
176
+ # Create new paramSet, configugre its identity
177
+ interfaceParamSet = createParamSet( Sbuilder::Constants::SWAGGER )
178
+ interfaceParamSet.setIdentity( path, op )
179
+ interfaceParamSet.setInfrastructureService( infrastructureServices )
180
+ @logger.info( "#{__method__} created interfaceParamSet=#{interfaceParamSet.getId}" )
181
+ @logger.debug( "#{__method__} created interfaceParamSet.getId=#{interfaceParamSet.getId}, opdef=#{opdef}" )
182
+
183
+ # add to array we are going to return
184
+ paramSets << interfaceParamSet
185
+
186
+ # ---------------------------------
187
+ # input paramters: 'paths'/<path>/<op>/'parameters'
188
+
189
+ # collect paramters to an array
190
+ # parameters = []
191
+ opdef['parameters'] && opdef['parameters'].map do |parameter|
192
+ @logger.debug( "#{__method__} path/op #{path}/#{op} - parameter #{parameter}" )
193
+ if parameter['schema'] then
194
+ # in='body' => schema defined
195
+ defintionReferenceName = getReferencedDefinitionName( parameter['schema'], swagger_hash )
196
+ reference_parameter( interfaceParamSet, parameter['name'], defintionReferenceName )
197
+ # parameters = parameters +
198
+ # # expand_reference_object( parameter['schema'], swagger_hash ).map do |schema|
199
+ # [ parameter['name'], schema ]
200
+ #end
201
+ elsif parameter['name']
202
+ simple_parameter( interfaceParamSet, parameter['name'], parameter['type'] ) if parameter['name']
203
+ # parameter object normal i.e. not in='body' object
204
+ # parameters << parameter2ParamObject( parameter )
205
+ else
206
+ msg = "Empty parameter definition on #{path}/#{op} "
207
+ @logger.error( "#{__method__} #{msg}" )
208
+ warn msg
209
+ end
210
+
211
+ end # parameters
212
+
213
+ # ------------------------------
214
+ # responses: 'paths'/<path>/<op>/'responses'
215
+
216
+ paramSetResponse = createParamSet( Sbuilder::Constants::SWAGGER )
217
+ paramSetResponse.setIdentity( path, 'response' )
218
+
219
+ # response response to an interface
220
+ interfaceParamSet.setResponse( paramSetResponse )
221
+
222
+
223
+ opdef['responses'] && opdef['responses'].each_pair do |status_code,response|
224
+ # puts "op=#{op}, status_code=#{status_code}, response=#{response}"
225
+
226
+ if response['schema'] then
227
+ defintionReferenceName = getReferencedDefinitionName( response['schema'], swagger_hash )
228
+ @logger.debug( "#{__method__} defintionReferenceName=#{defintionReferenceName}, op=#{op}, status_code=#{status_code}, response=#{response}" )
229
+ reference_parameter( paramSetResponse, "status_#{status_code}", defintionReferenceName, response['schema']['type'] )
230
+
231
+ else
232
+ @logger.debug( "#{path}-#{op}-#{status_code}: no response data for response #{response}" )
233
+ # # response object
234
+ end
235
+ end # opdef['responses'].each
236
+
237
+
238
+ end # each 'paths'
239
+ end
240
+
241
+ return paramSets
242
+ end
243
+
244
+
245
+
246
+ # return the name of definition referenced in 'paramOrRespSchema'
247
+ def getReferencedDefinitionName( paramOrRespSchema, swagger_hash )
248
+
249
+ # e.g. '#/definitions/doc
250
+ ref = getRef( paramOrRespSchema )
251
+
252
+ # e.g ['defintions', 'doc']
253
+ pathElements = getPathElementFromReference( ref )
254
+
255
+ # e.g. doc
256
+ definitionDocumentName = pathElements.last
257
+
258
+ # return the name
259
+ definitionDocumentName
260
+
261
+ end
262
+
263
+ # concat 'collectedReferences' with expanded '$ref' properties in 'definedDoc' with values in 'swagger_hash'
264
+ def expand_definedDocs( definedDoc, swagger_hash )
265
+
266
+ if definedDoc['properties']
267
+ return [ definedDoc['properties'] ]
268
+ # collect documents in 'allOf'
269
+ elsif definedDoc['allOf'] then
270
+ allDocs = []
271
+ definedDoc['allOf'].each do |elemenDoc|
272
+ allDocs = allDocs + definedDocArr2ParamObject(expand_definedDocs( elemenDoc, swagger_hash ))
273
+ end
274
+ # puts "---> expand_definedDocs-1 = #{allDocs} for #{definedDoc}"
275
+ return allDocs
276
+ else
277
+ # check for references
278
+ definedDoc.extend Hashie::Extensions::DeepFind
279
+ refs = definedDoc.deep_find_all( "$ref" )
280
+
281
+ if refs.nil?
282
+ puts "---> expand_definedDocs-2 = #{[definedDoc]} for #{definedDoc}"
283
+ return definedDocArr2ParamObject([definedDoc])
284
+ end
285
+ # expand all referncnes
286
+ expandedDocs = []
287
+ refs.each do |ref|
288
+ referredDoc = getDefinitionDoc( ref, swagger_hash )
289
+ expandedDocs = expandedDocs + definedDocArr2ParamObject(expand_definedDocs( referredDoc, swagger_hash ))
290
+ end
291
+
292
+ # puts "---> expand_definedDocs-3 = #{expandedDocs} for #{definedDoc}"
293
+ return expandedDocs
294
+ end # else not allOf
295
+
296
+ end
297
+
298
+ # 'properties' holds paramObject { <name>=>{}, <name>=>{}, ...}
299
+ def definedDocArr2ParamObject( definedDocArr )
300
+ definedDocArr.map { |e| e['properties'] ? e['properties'] : e }
301
+ end
302
+
303
+ # parameter hash {name: <name>, type:...} paramObject { <name>=>{}, <name>=>{}, ...}
304
+ def parameter2ParamObject( parameter )
305
+ return { parameter['name'] =>
306
+ {
307
+ "type" => parameter['type'],
308
+ "format" => parameter['format'],
309
+ } }
310
+ end
311
+
312
+
313
+ # get $ref from '$ref' or 'item.$ref'
314
+ def getRef( paramOrRespSchema )
315
+ return paramOrRespSchema['$ref'] if paramOrRespSchema['$ref']
316
+ return paramOrRespSchema['items']['$ref'] if paramOrRespSchema['items'] && paramOrRespSchema['items']['$ref']
317
+ raise "No ref found in #{paramOrRespSchema}"
318
+ end
319
+
320
+ def getRefDocumentName( paramOrRespSchema )
321
+
322
+
323
+ # --> /definitions/doc
324
+ ref = getRef( paramOrRespSchema )
325
+
326
+ # --> ['definitions', 'doc']
327
+ arrOfElement = getPathElementFromReference( ref )
328
+
329
+ # doc
330
+ arrOfElement.last
331
+
332
+ end
333
+
334
+ def hasRef( paramOrRespSchema )
335
+ return true if paramOrRespSchema['$ref']
336
+ return true if paramOrRespSchema['items'] && paramOrRespSchema['items']['$ref']
337
+ return false
338
+ end
339
+
340
+
341
+
342
+ # get document pointed by 'ref' in 'swagger_hash'
343
+ def getDefinitionDoc( ref, swagger_hash )
344
+ @logger.info( "#{__method__} ref=#{ref}" )
345
+
346
+
347
+ # currently supports only local references
348
+ raise "Not valid local ref #{ref} in #{schemaObject}" unless valid_local_ref( ref )
349
+
350
+ # '#/definitions/doc --> ['definitions', 'doc']
351
+ pathElements = getPathElementFromReference( ref )
352
+
353
+ # puts "pathElements=#{pathElements} for ref=#{ref} in #{refs}"
354
+ defininedDoc = swagger_hash.traverse( *pathElements )
355
+ @logger.debug( "#{__method__} ref=#{ref} --> defininedDoc=#{defininedDoc}" )
356
+ raise "Could not resolve definition reference '#{ref}'" if defininedDoc.nil?
357
+ defininedDoc
358
+ end
359
+
360
+ # '#/definitions/doc --> ['definitions', 'doc']
361
+ def getPathElementFromReference( ref )
362
+ pathElements = ref[2..-1].split( '/' )
363
+ end
364
+
365
+
366
+
367
+ # # process one pameter in swagger inferface
368
+ # def set_paramter_swagger( swagger_hash, paramSet, paramDef )
369
+ # @logger.debug( "#{__method__} paramSet=#{paramSet}, paramDef=#{paramDef}" )
370
+
371
+ # name = getProp( 'name', paramDef )
372
+ # inType = getProp( 'in', paramDef )
373
+
374
+ # if inType == 'body' then
375
+ # schema_parameter( paramSet, paramDef, swagger_hash )
376
+ # else
377
+ # simple_parameter( paramSet, name )
378
+ # end
379
+
380
+ # end
381
+
382
+ # process simple (i.e. non body ) parameter
383
+ def simple_parameter( paramSet, name, parameterType )
384
+
385
+ # create parameter object && configure it
386
+ swagger_parameter = createParameter( Sbuilder::Constants::PARAMETER )
387
+ swagger_parameter.setName( name )
388
+
389
+ # default for parameter 'not array' - set exlicitely array
390
+ swagger_parameter.setIsArray if parameterType == 'array'
391
+
392
+ @logger.info( "#{__method__} param set =#{paramSet.getId}, parameter name=#{swagger_parameter.getName}" )
393
+
394
+ # add to parameter set
395
+ paramSet.addParameter( swagger_parameter )
396
+
397
+ end
398
+
399
+ # process simple (i.e. non body ) parameter
400
+ def reference_parameter( paramSet, name, defintionReferenceName, parameterType="string" )
401
+
402
+ # create parameter object && configure it
403
+ swagger_parameter = createParameter( Sbuilder::Constants::PARAMETER_REF )
404
+ swagger_parameter.setName( name )
405
+ swagger_parameter.setReference( defintionReferenceName )
406
+ swagger_parameter.setIsArray if parameterType == 'array'
407
+
408
+ @logger.info( "#{__method__} param set =#{paramSet.getId}, parameter=#{swagger_parameter.getName}, parameter=#{swagger_parameter.reference}" )
409
+
410
+ # add to parameter set
411
+ paramSet.addParameter( swagger_parameter )
412
+
413
+ end
414
+
415
+
416
+ def valid_local_ref(ref)
417
+ ref.match(%r{\A#\/})
418
+ end
419
+
420
+
421
+
422
+ end # class ResolverLoaderSwagger << ResolverLoader
423
+
424
+ end # module Sbuilder