sbuilder-al 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.org +217 -0
- data/VERSION +1 -0
- data/design/al-language-bnf.org +216 -0
- data/lib/meta/etc.rb +265 -0
- data/lib/meta/meta.rb +106 -0
- data/lib/model/api.rb +678 -0
- data/lib/model/builders.rb +603 -0
- data/lib/model/constants.rb +24 -0
- data/lib/model/model.rb +534 -0
- data/lib/model/module.rb +25 -0
- data/lib/plugin/controller.rb +247 -0
- data/lib/plugin/module.rb +2 -0
- data/lib/plugin/plugin.rb +352 -0
- data/lib/sbuilder-al.rb +30 -0
- data/lib/translator/alrules.rb +424 -0
- data/lib/translator/module.rb +31 -0
- data/lib/translator/producer.rb +580 -0
- data/lib/translator/renderer.rb +159 -0
- data/lib/translator/sexp.rb +57 -0
- data/lib/translator/tlagenerator.rb +1348 -0
- data/lib/translator/translator.rb +210 -0
- data/lib/util/exception.rb +16 -0
- data/lib/util/logger.rb +90 -0
- data/lib/util/module.rb +16 -0
- data/lib/util/script_eval.rb +41 -0
- data/sbuilder-al.gemspec +45 -0
- metadata +153 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6f8c4a390b98790cf7eebeae8c39af57fff98657
|
4
|
+
data.tar.gz: f89df2d19fb85e6f1ccdbb6c19caa8ad38a87f61
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 69fe015460b662fc1e07f7b7e6cf6d308dcf4bc0062243b1cabed7e22a96774d5556f29e0a83e5c73022762d552e261e7c23a36fa6c026e5d827dceaa30da10b
|
7
|
+
data.tar.gz: 30d6f16c6884da322c0cd63b62b241d2c8c3b5687ebcd39c43b20136704e10fe55a91b45b9813bfddeebc0e17e4766c575425e6f8574fa43f633a237bb66bfb7
|
data/README.org
ADDED
@@ -0,0 +1,217 @@
|
|
1
|
+
* =sbuilder-al=: an API Language Interface to =tla-sbuilder= -Tool
|
2
|
+
|
3
|
+
=tla-sbuilder= is tool to generate runnable formal models in [[http://research.microsoft.com/en-us/um/people/lamport/tla/book.html][TLA+
|
4
|
+
language]] for [[https://github.com/jarjuk/tla-sbuilder#TARGET-SYSTEM][business IT systems]]. A formal model can be [[https://en.wikipedia.org/wiki/Model_checking][model
|
5
|
+
checked]] using [[http://research.microsoft.com/en-us/um/people/lamport/tla/tools.html][TLA+ Tools]].
|
6
|
+
|
7
|
+
=sbuillder-al= defines an [[design/al-language-bnf.org][API Language]] (AL), which it maps to [[https://github.com/jarjuk/tla-sbuilder#API_LOADER][API
|
8
|
+
Loader]] and [[https://github.com/jarjuk/tla-sbuilder#SNIPPET_LOADER][Snippet Loader]] extension points in =tla-sbuilder=.
|
9
|
+
|
10
|
+
Normally, there is no need to install =sbuilder-al= separately
|
11
|
+
because =sbuilder-al= is included as dependency for higher level
|
12
|
+
interfaces. For example, [[https://github.com/jarjuk/sbuilder-eth][sbuilder-eth]] GEM, Ethereum Solidity
|
13
|
+
interface to =tla-sbuilder=, uses =sbuilder-al= to interface with
|
14
|
+
=tla-sbuilder=.
|
15
|
+
|
16
|
+
* Development
|
17
|
+
|
18
|
+
** Run Rspec Unit Tests
|
19
|
+
|
20
|
+
To run =rspec= unit tests
|
21
|
+
|
22
|
+
#+name rspec
|
23
|
+
#+BEGIN_SRC sh :eval no-export :results output :exports code
|
24
|
+
bundle exec rspec
|
25
|
+
#+END_SRC
|
26
|
+
|
27
|
+
#+RESULTS:
|
28
|
+
#+begin_example
|
29
|
+
...................*.......................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
|
30
|
+
|
31
|
+
Pending: (Failures listed here are expected and do not affect your suite's status)
|
32
|
+
|
33
|
+
1) Sbuilder::Al::Meta::Etc.alObject2ApiString domain
|
34
|
+
# causes dump
|
35
|
+
# ./spec/meta/etc_spec.rb:113
|
36
|
+
|
37
|
+
Finished in 0.4775 seconds (files took 0.49587 seconds to load)
|
38
|
+
1659 examples, 0 failures, 1 pending
|
39
|
+
|
40
|
+
#+end_example
|
41
|
+
|
42
|
+
|
43
|
+
** Run Cucumber Tests
|
44
|
+
|
45
|
+
To run =cucumber= tests
|
46
|
+
|
47
|
+
#+name cucumber
|
48
|
+
#+BEGIN_SRC sh :eval no-export :results output :exports code
|
49
|
+
bundle exec cucumber
|
50
|
+
#+END_SRC
|
51
|
+
|
52
|
+
#+RESULTS:
|
53
|
+
: Using the default profile...
|
54
|
+
: ...........................................................................
|
55
|
+
:
|
56
|
+
: 6 scenarios (6 passed)
|
57
|
+
: 75 steps (75 passed)
|
58
|
+
: 0m8.028s
|
59
|
+
|
60
|
+
|
61
|
+
* Usage (Normally not needed)
|
62
|
+
:PROPERTIES:
|
63
|
+
:CUSTOM_ID: MANUAL-USAGE
|
64
|
+
:END:
|
65
|
+
|
66
|
+
Following short steps demonstrate, how =sbuilder-al= loads AL snippets
|
67
|
+
to =tla-sbuilder= context.
|
68
|
+
|
69
|
+
** Create Gemfile
|
70
|
+
|
71
|
+
Configure =sbuilder-al= into =Gemfile=
|
72
|
+
|
73
|
+
#+BEGIN_SRC ruby :eval no
|
74
|
+
source "https://rubygems.org"
|
75
|
+
gem "sbuilder-al"
|
76
|
+
#+END_SRC
|
77
|
+
|
78
|
+
and install it together with dependencies:
|
79
|
+
|
80
|
+
#+BEGIN_SRC sh :eval no
|
81
|
+
bundle install
|
82
|
+
#+END_SRC
|
83
|
+
|
84
|
+
** Initialize =tla-sbuilder= directory structure
|
85
|
+
|
86
|
+
Command
|
87
|
+
|
88
|
+
#+name: sbuilder-init
|
89
|
+
#+BEGIN_SRC sh :eval no-export :results output :exports code
|
90
|
+
bundle exec sbuilder.rb init
|
91
|
+
#+END_SRC
|
92
|
+
|
93
|
+
creates directory structure for running tla-sbuilder.
|
94
|
+
|
95
|
+
#+RESULTS: sbuilder-init
|
96
|
+
#+begin_example
|
97
|
+
Directory cnf - created
|
98
|
+
Directory cache - already exists - no need to create
|
99
|
+
Directory src - created
|
100
|
+
Directory src/extend - created
|
101
|
+
Directory gen - created
|
102
|
+
File cnf/sbuilder.yaml.example - created
|
103
|
+
File cnf/resolver_customer.yaml.example - created
|
104
|
+
File cnf/extend_customer_doms.yaml.example - created
|
105
|
+
File cnf/extend_customer_if.yaml.example - created
|
106
|
+
File cnf/extend_customer_run1.yaml.example - created
|
107
|
+
File cnf/extend_customer_run2.yaml.example - created
|
108
|
+
File cnf/interface_customer.yaml.example - created
|
109
|
+
#+end_example
|
110
|
+
|
111
|
+
|
112
|
+
** Create Configuration File =cnf/sbuider.yaml=
|
113
|
+
|
114
|
+
Create a configuration file =cnf/sbuilder.yaml= with the following YAML content
|
115
|
+
|
116
|
+
#+BEGIN_SRC yaml :eval no :tangle cnf/sbuilder.yaml
|
117
|
+
|
118
|
+
# Define 'sbuilder-al' extension point
|
119
|
+
extend:
|
120
|
+
loaders:
|
121
|
+
- className: Sbuilder::Al::Plugin::Plugin
|
122
|
+
gem: sbuilder-al
|
123
|
+
objects:
|
124
|
+
# define object 'alLoader' and configure it
|
125
|
+
- objectName: alLoader
|
126
|
+
configuration:
|
127
|
+
metatypes:
|
128
|
+
example:
|
129
|
+
description: Example metatype using ex prefix
|
130
|
+
prefix: ex
|
131
|
+
rubypaths:
|
132
|
+
- src/al.rb
|
133
|
+
|
134
|
+
# Run as API loader extension point
|
135
|
+
interfaces:
|
136
|
+
- objectName: alLoader
|
137
|
+
|
138
|
+
# Run as Snippet loader extension point
|
139
|
+
snippets:
|
140
|
+
- objectName: alLoader
|
141
|
+
|
142
|
+
|
143
|
+
# Define setup with name 'setup1'
|
144
|
+
setups:
|
145
|
+
- setupDirectory: setup1
|
146
|
+
|
147
|
+
#+END_SRC
|
148
|
+
|
149
|
+
** Create Api Langauage file =src/al=
|
150
|
+
|
151
|
+
Create a simple AL language module, which defines an API object
|
152
|
+
=alApi= to construct AL language objects in an array
|
153
|
+
|
154
|
+
#+BEGIN_SRC ruby eval :no exports :code :tangle src/al.rb
|
155
|
+
|
156
|
+
# Include GEM
|
157
|
+
require('sbuilder-al')
|
158
|
+
|
159
|
+
# Define api interface to tla-sbuilder
|
160
|
+
class AlApi
|
161
|
+
include Sbuilder::Al::Model::Api
|
162
|
+
end
|
163
|
+
|
164
|
+
nameSpaces = { "example" => { :description=>"Example namespace", :prefix=>"ex_" } }
|
165
|
+
alApi = AlApi.start( nameSpaces )
|
166
|
+
|
167
|
+
|
168
|
+
# Application is an array of AL elements
|
169
|
+
[
|
170
|
+
alApi.variable( "example") do
|
171
|
+
name "var1"
|
172
|
+
init alApi.constantExpression { value "Hello World" }
|
173
|
+
end,
|
174
|
+
|
175
|
+
]
|
176
|
+
|
177
|
+
|
178
|
+
#+END_SRC
|
179
|
+
|
180
|
+
** Generate sbuilder
|
181
|
+
|
182
|
+
Running
|
183
|
+
|
184
|
+
#+name: sbuilder-gen
|
185
|
+
#+BEGIN_SRC sh :eval no-export :results output :exports code
|
186
|
+
bundle exec sbuilder.rb generate setup1
|
187
|
+
#+END_SRC
|
188
|
+
|
189
|
+
#+RESULTS: sbuilder-gen
|
190
|
+
|
191
|
+
creates a file
|
192
|
+
|
193
|
+
#+name: sbuilder-ls
|
194
|
+
#+BEGIN_SRC sh :eval no-export :results output :exports code
|
195
|
+
ls -l gen/setup1/tla/model.tla
|
196
|
+
#+END_SRC
|
197
|
+
|
198
|
+
#+RESULTS: sbuilder-ls
|
199
|
+
: -rw-rw-r-- 1 jj jj 16242 joulu 18 10:36 gen/setup1/tla/model.tla
|
200
|
+
|
201
|
+
which defines variable =ev_var1=
|
202
|
+
|
203
|
+
#+name: sbuilder-grep
|
204
|
+
#+BEGIN_SRC sh :eval no-export :results output :exports code
|
205
|
+
grep 'Hello' gen/setup1/tla/model.tla
|
206
|
+
#+END_SRC
|
207
|
+
|
208
|
+
#+RESULTS: sbuilder-grep
|
209
|
+
: ex_var1 = "Hello World";
|
210
|
+
|
211
|
+
|
212
|
+
for the AL snippet created in =src/al.rb= module.
|
213
|
+
|
214
|
+
|
215
|
+
* License
|
216
|
+
|
217
|
+
MIT
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.8
|
@@ -0,0 +1,216 @@
|
|
1
|
+
#+BEGIN_EXAMPLE
|
2
|
+
|
3
|
+
# Top level application
|
4
|
+
<application> :: <snippet>*
|
5
|
+
<snippet> :: <apiSnippet> | <tlaSnippet>
|
6
|
+
|
7
|
+
# Api snippets
|
8
|
+
<apiSnippet> :: <transaction> | <definition> | <domain>
|
9
|
+
|
10
|
+
<domain> :: =domain= { =name= STRING,
|
11
|
+
[
|
12
|
+
=value= STRING |
|
13
|
+
=value= INT |
|
14
|
+
=value= true |
|
15
|
+
=value= false |
|
16
|
+
=literal= STRING
|
17
|
+
]*
|
18
|
+
}
|
19
|
+
|
20
|
+
<definition> :: =definition= {
|
21
|
+
=name= STRING
|
22
|
+
<property>*
|
23
|
+
}
|
24
|
+
|
25
|
+
|
26
|
+
<property> :: =property= {
|
27
|
+
=name= STRING
|
28
|
+
=domain= STRING
|
29
|
+
=isArray= BOOLEAN
|
30
|
+
} |
|
31
|
+
=property= {
|
32
|
+
=name= STRING
|
33
|
+
=definition= STRING
|
34
|
+
=isArray= BOOLEAN
|
35
|
+
}
|
36
|
+
|
37
|
+
# TLA & API snippets
|
38
|
+
<transaction> :: =transaction= <meta> {
|
39
|
+
=name= STRING
|
40
|
+
(=local= STRING)*
|
41
|
+
=interfaceOption= <booleanExpression>
|
42
|
+
=returnOption= <booleanExpression>
|
43
|
+
=request= <request>
|
44
|
+
=response= <response>
|
45
|
+
=operation= STRING
|
46
|
+
=block= <block>
|
47
|
+
}
|
48
|
+
|
49
|
+
<request> :: =request= {
|
50
|
+
<reqResponseParam>*
|
51
|
+
}
|
52
|
+
<response> :: =response= {
|
53
|
+
<reqResponseParam>*
|
54
|
+
}
|
55
|
+
<reqResponseParam> :: =parameter= <name> <isArray> [ <domainName> ] |
|
56
|
+
=reference= <name> <isArray> <definitionName>
|
57
|
+
<isArray> :: true | false
|
58
|
+
|
59
|
+
|
60
|
+
# TLA snippets
|
61
|
+
<tlaSnippet> :: <transaction> | <macro> | <operator> | <variable> | <alias>
|
62
|
+
<macro> :: =macro= <meta> {
|
63
|
+
=name= STRING
|
64
|
+
(=parameter= <STRING>)*
|
65
|
+
=block= <block>
|
66
|
+
}
|
67
|
+
|
68
|
+
<alias> :: =aliased=(<meta> ) {
|
69
|
+
=name= STRING
|
70
|
+
=specName= STRING
|
71
|
+
}
|
72
|
+
|
73
|
+
<operator> :: =operator= <meta> {
|
74
|
+
=name= STRING
|
75
|
+
(=parameter= <STRING>)*
|
76
|
+
<operatorParameter>*
|
77
|
+
=expression= <expression>
|
78
|
+
}
|
79
|
+
|
80
|
+
# Block && statements
|
81
|
+
<block> :: <statement>*
|
82
|
+
<statement> :: <outputStmt> | <skipStmt> | <labelStmt> |
|
83
|
+
<callService> | <callMacro> | <conditionalStmt> | <assignTo> |
|
84
|
+
<ReturnValue> | <Return> | <jump> | <aborted> | <done> | <failure>
|
85
|
+
|
86
|
+
<skipStmt> :: =nop=
|
87
|
+
<labelStmt> :: =label=
|
88
|
+
<outputStmt> :: =output= <expression>*
|
89
|
+
|
90
|
+
<assignTo> :: =assignTo= {
|
91
|
+
=variable= <parameterRVal>
|
92
|
+
=rval= <expression>
|
93
|
+
} |
|
94
|
+
=assignTo= {
|
95
|
+
=variable= <reference>
|
96
|
+
=rval= <expression>
|
97
|
+
}
|
98
|
+
|
99
|
+
<reference> :: <referenceLocation> ('.' STRING)*
|
100
|
+
<referenceLocation> :: <txParameterRef> | <simpleRef> | <variableRef>
|
101
|
+
<simpleRef> :: STRING
|
102
|
+
<variableRef> :: <meta> STRING
|
103
|
+
<txParameterRef> :: <meta> STRING STRING
|
104
|
+
|
105
|
+
<lval> :: <parameterReference> | <variableReference>
|
106
|
+
|
107
|
+
<callService> :: =callService= <meta> <name> <operation> {
|
108
|
+
(=parameter= <expression>)*
|
109
|
+
}
|
110
|
+
<callMacro> :: =callMacro= <meta> <name> {
|
111
|
+
(=parameter= <expression>)*
|
112
|
+
}
|
113
|
+
<conditionalStmt> :: =ifThen= <expression> <block> ( =elseThen <block> )?
|
114
|
+
|
115
|
+
|
116
|
+
<jump> :: =jump= STRING
|
117
|
+
|
118
|
+
<aborted> :: =aborted= <interfaceOpration>
|
119
|
+
<done> :: =done= <interfaceOpration>
|
120
|
+
<failure> :: =done= <interfaceOpration>
|
121
|
+
|
122
|
+
<return> :: =ret= <booleanExpression>
|
123
|
+
|
124
|
+
<ReturnValue> :: =returnValue= STRING <expression>
|
125
|
+
|
126
|
+
# expressions
|
127
|
+
<expression> :: <constantExpression> |
|
128
|
+
<referenceExpression> |
|
129
|
+
<tlaExpression> |
|
130
|
+
<operatorCall> |
|
131
|
+
<binaryExpression>
|
132
|
+
<unaryExpression>
|
133
|
+
|
134
|
+
<operatorCall> :: *TBD*
|
135
|
+
|
136
|
+
<referenceExpression>:: =reference= <reference>
|
137
|
+
|
138
|
+
|
139
|
+
<operatorExpression> :: =parameterReference= STRING
|
140
|
+
|
141
|
+
<tlaExpression> :: =tlaExpression= {
|
142
|
+
=template= <tlaTemplate>
|
143
|
+
=args= <expression>*
|
144
|
+
}
|
145
|
+
<tlaTemplate> :: =:set= | =:sequence= | =:nil= | =:parenthesis=
|
146
|
+
|
147
|
+
<binaryExpression> :: =binaryExpression= {
|
148
|
+
=lval= <expression>
|
149
|
+
=op= <binaryOp>
|
150
|
+
=rval= <expression>
|
151
|
+
}
|
152
|
+
|
153
|
+
<unaryExpression> :: =unaryExpression= {
|
154
|
+
=op= <unaryOp>
|
155
|
+
=expr= <expression>
|
156
|
+
}
|
157
|
+
|
158
|
+
<binaryOp> :: =:plus= | =:minus= | =:equal= | =:mult= | =:div= | =:lt= | =:le=
|
159
|
+
<unaryOp> :: =:not
|
160
|
+
|
161
|
+
<constantExpression> :: <integerExpression> | <stringExpression> | <booleanExpression>
|
162
|
+
<booleanExpression> :: <trueExpression> | <falseExpression>
|
163
|
+
<trueExpression> :: TRUE
|
164
|
+
<falseExpression> :: FALSE
|
165
|
+
<stringExpression> :: STRING
|
166
|
+
<integerExpression> :: INT
|
167
|
+
|
168
|
+
|
169
|
+
# Namespace meta
|
170
|
+
<meta> :: <sbuilderMetatype> | STRING
|
171
|
+
<name> :: STRING
|
172
|
+
<domainName> :: STRING
|
173
|
+
<definitionName> :: STRING
|
174
|
+
<sbuilderMetatype> :: 'domains' | 'service_implementation' | 'service_completion' | 'framework-svc'
|
175
|
+
|
176
|
+
#+END_EXAMPLE
|
177
|
+
|
178
|
+
TLA-templates
|
179
|
+
|
180
|
+
#+BEGIN_EXAMPLE
|
181
|
+
tlaSet(expression) :: tlaExpression {
|
182
|
+
tempalate :tlaSet
|
183
|
+
args expr
|
184
|
+
}
|
185
|
+
|
186
|
+
|
187
|
+
tlaNil :: tlaExpression {
|
188
|
+
tempalate :nil
|
189
|
+
}
|
190
|
+
|
191
|
+
tlaSequence(expr) :: =tlaExpression= {
|
192
|
+
tempalate :sequence
|
193
|
+
arg= expr
|
194
|
+
}
|
195
|
+
tlaParenthesis(expr) :: =tlaExpression= {
|
196
|
+
tempalate :parenthesis
|
197
|
+
arg= expr
|
198
|
+
}
|
199
|
+
|
200
|
+
tlaPlainname :: =tlaPlainname= STRING
|
201
|
+
tlaRecodrIndex :: =tlaRecordIndex= STRING <tlaExpression>
|
202
|
+
tlaIF :: =tlaIF= <tlaExpression> <tlaExpression> <tlaExpression>
|
203
|
+
tlaEXCEPT :: =tlaEXCEPT= STRING <tlaExpression>
|
204
|
+
tlaSetGenerator :: =tlaEXCEPT= <tlaExpression> STRING <tlaExpression>
|
205
|
+
tlaSetIterate(v,set) :: tlaExpression {
|
206
|
+
tempalate :set_iterate
|
207
|
+
args v
|
208
|
+
args set
|
209
|
+
}
|
210
|
+
|
211
|
+
=plus=(l,r) :: =binaryExpression= { =lval= l; =op= :plus; =rval= r }
|
212
|
+
=minus(l,r) :: =binaryExpression= { =lval= l; =op= :minus; =rval r }
|
213
|
+
=equal(l,r) :: =binaryExpression= { =lval= l; =op= :equal; =rval= r }
|
214
|
+
=unequal(l,r) :: =binaryExpression= { =lval= l; =op= :unequal; =rval= r }
|
215
|
+
|
216
|
+
#+END_EXAMPLE
|
data/lib/meta/etc.rb
ADDED
@@ -0,0 +1,265 @@
|
|
1
|
+
require "sbuilder"
|
2
|
+
module Sbuilder
|
3
|
+
module Al
|
4
|
+
module Meta
|
5
|
+
module Etc
|
6
|
+
|
7
|
+
## Define lambdas for plantUml strings
|
8
|
+
STR_CLASSNODE =
|
9
|
+
lambda do |kl, attributes=false|
|
10
|
+
"
|
11
|
+
class #{kl.respond_to?(:demodulize) ? kl.demodulize : kl } {
|
12
|
+
#{ kl.attributes.join("\n") if (attributes && kl.respond_to?(:attributes) ) }
|
13
|
+
}
|
14
|
+
"
|
15
|
+
end
|
16
|
+
|
17
|
+
STR_MODULENODE =
|
18
|
+
lambda do |modu, attributes=false|
|
19
|
+
"
|
20
|
+
package #{modu.to_s.split("::").last } {
|
21
|
+
}
|
22
|
+
"
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
STR_EDGE =
|
27
|
+
lambda do |kl, chld|
|
28
|
+
"#{kl.respond_to?(:demodulize) ? kl.demodulize : kl } <|-- #{chld.respond_to?(:demodulize) ? chld.demodulize : chld}"
|
29
|
+
end
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
# @return [Array<class>] Class hierarchy recursable using
|
34
|
+
# 'descendants' method without classess below array 'prune'
|
35
|
+
#
|
36
|
+
# @param klass [class] to start of hierarchy collection
|
37
|
+
#
|
38
|
+
# @param classes [Array<class>] collected so far
|
39
|
+
#
|
40
|
+
# @param prune [Array<class>] hierarchy pruned away below the
|
41
|
+
# classes in 'prune' - array
|
42
|
+
def self.hierarchy( klass, prune=[], classes=[] )
|
43
|
+
classes += klass.descendants.map { |kl| hierarchy( kl, prune, classes ) }.flatten if klass.respond_to?( :descendants ) && !prune.include?(klass)
|
44
|
+
classes = classes << klass
|
45
|
+
classes.uniq
|
46
|
+
end
|
47
|
+
|
48
|
+
# @return [Array<class>] of ancestor classes defining
|
49
|
+
# ':descendants' method
|
50
|
+
def self.ancestors( klass, classes=[] )
|
51
|
+
if klass.superclass.respond_to?( :descendants )
|
52
|
+
classes += ancestors( klass.superclass, classes )
|
53
|
+
classes.unshift( klass.superclass)
|
54
|
+
end
|
55
|
+
classes
|
56
|
+
end
|
57
|
+
|
58
|
+
# @return [Array<[Class,Class]>] Array of child, parent arrays
|
59
|
+
def self.parentEdges( klasses )
|
60
|
+
klasses.reduce([] ) do |memo, kl|
|
61
|
+
# puts "kl.class.ancestors=#{kl.class.ancestors}"
|
62
|
+
#memo = memo + ((klasses - [kl]) & kl.class.ancestors ).map{ |kl2| [kl,kl2]}
|
63
|
+
memo << [kl,kl.superclass] if klasses.include?(kl.superclass)
|
64
|
+
memo
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# @return [Array<Class>] of classes in myModule, excluding
|
69
|
+
# classes in 'excluded'
|
70
|
+
def self.moduleClasses( myModule, excluded=[] )
|
71
|
+
myModule.
|
72
|
+
# acces module constants
|
73
|
+
constants.
|
74
|
+
# select not excluded classes
|
75
|
+
select do |c|
|
76
|
+
klass = myModule.const_get(c, inherit=false)
|
77
|
+
klass.is_a?(Class) && ( klass.ancestors & excluded ).empty?
|
78
|
+
end.
|
79
|
+
# map 'em class symbols to Class objects
|
80
|
+
map { |c| myModule.const_get(c, inherit=false) }
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
# @return [Array<Module>] of Module in myModule, excluding
|
85
|
+
# classes in 'excluded'
|
86
|
+
def self.moduleSubModules( myModule, excluded=[] )
|
87
|
+
myModule.constants.
|
88
|
+
map { |c| myModule.const_get(c, inherit=false) }.
|
89
|
+
select { |c| c.class == Module } # && !excluded.include?( c ) }
|
90
|
+
# # map 'em class symbols to Class objects
|
91
|
+
# map { |c| myModule.const_get(c, inherit=false) }
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
##
|
96
|
+
# Render 'alObject' as a string
|
97
|
+
#
|
98
|
+
# @param alObject [AlObject] AL language object to render as atring
|
99
|
+
#
|
100
|
+
def self.snippetString( alObject )
|
101
|
+
Sbuilder::Al::Plugin::Controller.start.alObject2tlaString( alObject )
|
102
|
+
end
|
103
|
+
|
104
|
+
# Class overriding configuration reader for Sbuilder
|
105
|
+
class MyController < Sbuilder::Controller
|
106
|
+
def initialize( factory, sbuilderConfigs )
|
107
|
+
@sbuilderConfigs = sbuilderConfigs
|
108
|
+
super( factory )
|
109
|
+
end
|
110
|
+
# Method to reaturn 'sbuilder.yaml' sbuilder overridden
|
111
|
+
def getConfigSbuilder
|
112
|
+
@sbuilderConfigs
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
##
|
119
|
+
# Render 'apiElement' as a string
|
120
|
+
#
|
121
|
+
# @param apiElement [Hash] A hash to define api element
|
122
|
+
#
|
123
|
+
def self.alObject2ApiString( alObject, alObjectCtx = [])
|
124
|
+
|
125
|
+
|
126
|
+
# Configure
|
127
|
+
apiType2Config = {
|
128
|
+
:domain => {
|
129
|
+
"modelData" => "domains",
|
130
|
+
"template" => "domains.mustache",
|
131
|
+
},
|
132
|
+
:definition => {
|
133
|
+
"modelData" => "definitions",
|
134
|
+
"template" => "definition_types.mustache",
|
135
|
+
},
|
136
|
+
}
|
137
|
+
|
138
|
+
# Init sbuilder factory & controller & define configuration
|
139
|
+
sbuilderConfigs = {
|
140
|
+
"setups" => [
|
141
|
+
{
|
142
|
+
"setupDirectory": "example"
|
143
|
+
}
|
144
|
+
]
|
145
|
+
}
|
146
|
+
factory = Sbuilder::Factory.getFactory()
|
147
|
+
sbuilderController = MyController.new( factory, sbuilderConfigs )
|
148
|
+
|
149
|
+
# use sbuilder factory to instantiate API plugin && configure it
|
150
|
+
apiFacade = factory.getApiFacade(sbuilderController)
|
151
|
+
plugin = factory.getLoaderPlugin( Sbuilder::Al::Plugin::Plugin )
|
152
|
+
plugin.setFacade(apiFacade)
|
153
|
+
|
154
|
+
# Add translated element of interest to plugin 'application'
|
155
|
+
# (=state kept in controller)
|
156
|
+
apiElement = plugin.controller.alObject2tlaSexp( alObject )
|
157
|
+
raise "Expect :apiType property in #{apiElement}" unless apiElement.has_key?( :apiType )
|
158
|
+
|
159
|
+
apiElementCtx = alObjectCtx.map{ |o| plugin.controller.alObject2tlaSexp( alObject ) }
|
160
|
+
|
161
|
+
plugin.controller.addAlObjects( apiElementCtx )
|
162
|
+
plugin.controller.addAlObjects( apiElement )
|
163
|
+
|
164
|
+
# sbuilderController.load
|
165
|
+
|
166
|
+
sbuilderController.baseExtensionDefine
|
167
|
+
|
168
|
+
# invoke plugin API loader interface to pass data to sbuilder
|
169
|
+
plugin.load( nil )
|
170
|
+
|
171
|
+
# After load prepare for snippets stuff
|
172
|
+
sbuilderController.resolve
|
173
|
+
sbuilderController.initializeSymbolTableMetaModel
|
174
|
+
sbuilderController.initializeSymbolTable
|
175
|
+
|
176
|
+
|
177
|
+
# render template in sbuilder
|
178
|
+
setupName = "example"
|
179
|
+
outputPath = "output"
|
180
|
+
# choose template && data which to show
|
181
|
+
raise "Unknown apiType '#{apiElement[:apiType]}', valid apitype #{apiType2Config.keys.join(',')}" if apiType2Config[apiElement[:apiType]].nil?
|
182
|
+
generateDef = { "template" => apiType2Config[apiElement[:apiType]]["template"],
|
183
|
+
"desc"=>"example",
|
184
|
+
"modelData" => apiType2Config[apiElement[:apiType]]["modelData"],
|
185
|
+
}
|
186
|
+
mustache = sbuilderController.prepareRender( setupName )
|
187
|
+
sbuilderController.generateTemplateString( setupName, outputPath, generateDef, mustache)
|
188
|
+
end
|
189
|
+
|
190
|
+
|
191
|
+
|
192
|
+
# @return [Array<String>] Class hierarchy edges and nodes for
|
193
|
+
# class 'klass' with classes in 'prune'
|
194
|
+
#
|
195
|
+
# @param attributes [Boolean] true when include attributes to class default
|
196
|
+
#
|
197
|
+
# @param parents [Boolean] true when include also parent to hierarchy
|
198
|
+
def self.plantUmlClassHierarchy( klass, prune=[], attributes=false, parents=false )
|
199
|
+
klass = [klass] unless klass.is_a?( Array )
|
200
|
+
|
201
|
+
# Find all classes in hierarchy 'klass'
|
202
|
+
klassesInHierarchy =
|
203
|
+
klass.map do |kl|
|
204
|
+
hierarchy( kl, prune )
|
205
|
+
end.flatten
|
206
|
+
|
207
|
+
## Create edge strings for hierarch down
|
208
|
+
hierarchyEdges =
|
209
|
+
klassesInHierarchy.
|
210
|
+
# do not look into descendants of a pruned class
|
211
|
+
select{ |kl| !prune.include?(kl) }.
|
212
|
+
map do |kl|
|
213
|
+
# kl.descendants.map { |chld| "#{kl.demodulize} <|-- #{chld.demodulize}" }
|
214
|
+
kl.descendants.map { |chld| STR_EDGE.call( kl, chld ) }
|
215
|
+
end.flatten
|
216
|
+
|
217
|
+
## Create node string
|
218
|
+
hierarchyNodes =
|
219
|
+
klassesInHierarchy.map do |kl|
|
220
|
+
STR_CLASSNODE.call( kl, attributes )
|
221
|
+
end
|
222
|
+
|
223
|
+
|
224
|
+
parentNodes = []
|
225
|
+
parentEdges = []
|
226
|
+
|
227
|
+
if ( parents ) then
|
228
|
+
|
229
|
+
# string for all parent nodes
|
230
|
+
parentNodes = klass.map do |kl|
|
231
|
+
# find all ancestors for all classes
|
232
|
+
ancestors( kl )
|
233
|
+
end.flatten.uniq.map do |kl|
|
234
|
+
# and a node for them
|
235
|
+
STR_CLASSNODE.call( kl, attributes )
|
236
|
+
end
|
237
|
+
|
238
|
+
parentEdges = klass.reduce([]) do |memo,kl|
|
239
|
+
|
240
|
+
klWithAncestors = [kl] + ancestors( kl )
|
241
|
+
# puts( "klWithAncestors=#{klWithAncestors.join(',')}")
|
242
|
+
memo << (0..(klWithAncestors.length-2)).map do |i|
|
243
|
+
# puts( "i=#{i}, klWithAncestors.length=#{klWithAncestors.length}, klWithAncestors[i]=#{klWithAncestors[i]}, #{klWithAncestors[i+1]}")
|
244
|
+
# template 'strEdge' produces parent/sub-class edge
|
245
|
+
# [ klWithAncestors[i+1], klWithAncestors[i] ]
|
246
|
+
STR_EDGE.call(klWithAncestors[i+1], klWithAncestors[i])
|
247
|
+
end
|
248
|
+
memo
|
249
|
+
end.reject{ |arr| arr.empty? }
|
250
|
+
# puts( "parentEdges=#{parentEdges.length}=#{parentEdges.join(',')},#{parentEdges}")
|
251
|
+
|
252
|
+
|
253
|
+
end # parents
|
254
|
+
|
255
|
+
# make edges unique
|
256
|
+
parentEdges = parentEdges.flatten.uniq
|
257
|
+
hierarchyEdges = hierarchyEdges.flatten.uniq
|
258
|
+
|
259
|
+
hierarchyNodes + parentNodes + parentEdges + hierarchyEdges
|
260
|
+
end
|
261
|
+
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end # Al
|
265
|
+
end # Sbuilder
|