activefacts-compositions 1.9.22 → 1.9.23
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 +5 -5
- data/README.md +1 -1
- data/activefacts-compositions.gemspec +1 -1
- data/bin/schema_compositor +71 -27
- data/lib/activefacts/compositions/binary.rb +4 -0
- data/lib/activefacts/compositions/datavault.rb +4 -0
- data/lib/activefacts/compositions/relational.rb +4 -0
- data/lib/activefacts/compositions/staging.rb +4 -0
- data/lib/activefacts/compositions/version.rb +1 -1
- data/lib/activefacts/generator/doc/css/glossary-print.css +72 -0
- data/lib/activefacts/generator/doc/css/glossary.css +194 -0
- data/lib/activefacts/generator/doc/css/ldm.css +12 -17
- data/lib/activefacts/generator/doc/css/orm2-print.css +19 -0
- data/lib/activefacts/generator/doc/css/orm2.css +28 -0
- data/lib/activefacts/generator/doc/css/reset.css +18 -0
- data/lib/activefacts/generator/doc/css/treetable.css +83 -0
- data/lib/activefacts/generator/doc/cwm.rb +60 -54
- data/lib/activefacts/generator/doc/glossary.rb +261 -137
- data/lib/activefacts/generator/doc/graphviz.rb +6 -2
- data/lib/activefacts/generator/doc/ldm.rb +7 -3
- data/lib/activefacts/generator/etl/unidex.rb +7 -2
- data/lib/activefacts/generator/oo.rb +2 -1
- data/lib/activefacts/generator/population.rb +174 -0
- data/lib/activefacts/generator/rails/active_admin.rb +81 -0
- data/lib/activefacts/generator/rails/application_record_shell.rb +78 -0
- data/lib/activefacts/generator/rails/models.rb +31 -72
- data/lib/activefacts/generator/rails/ruby_folder_generator.rb +87 -0
- data/lib/activefacts/generator/rails/schema.rb +12 -4
- data/lib/activefacts/generator/ruby.rb +7 -3
- data/lib/activefacts/generator/sql.rb +2 -1
- data/lib/activefacts/generator/summary.rb +24 -19
- data/lib/activefacts/generator/traits/sql.rb +4 -0
- data/lib/activefacts/generator/transgen.rb +7 -1
- data/lib/activefacts/generator/validate.rb +10 -2
- metadata +15 -5
@@ -1,33 +1,28 @@
|
|
1
|
-
a:link, a:visited {
|
2
|
-
color: #8A0092; text-decoration: underline;
|
3
|
-
}
|
4
|
-
|
5
|
-
span {
|
6
|
-
font-family: "Frutiger", sans-serif;
|
7
|
-
}
|
8
|
-
|
9
1
|
.keyword {
|
10
2
|
color: #0000CC;
|
11
3
|
}
|
12
4
|
|
13
|
-
.term, .concept {
|
5
|
+
.schema, .term, .concept {
|
14
6
|
/* Xcolor: #6A0072; The color used by NORMA */
|
15
7
|
color: #8A0092;
|
16
8
|
}
|
17
9
|
|
18
|
-
.
|
19
|
-
/* Xcolor: #6A0072; The color used by NORMA */
|
20
|
-
color: #8A0092;
|
21
|
-
}
|
22
|
-
|
23
|
-
.linking, .reading {
|
10
|
+
.reading {
|
24
11
|
color: #0E5400;
|
25
12
|
}
|
26
13
|
|
27
|
-
.
|
14
|
+
.value {
|
28
15
|
color: #FF990E;
|
29
16
|
}
|
30
17
|
|
18
|
+
a:link, a:visited {
|
19
|
+
color: #8A0092; text-decoration: underline;
|
20
|
+
}
|
21
|
+
|
22
|
+
span {
|
23
|
+
font-family: "Helvetica Neue", Helvetica,"Arial Unicode MS", Arial, sans-serif;
|
24
|
+
}
|
25
|
+
|
31
26
|
.glossary-objectification .glossary-reading {
|
32
27
|
margin-left: 30px;
|
33
28
|
}
|
@@ -42,4 +37,4 @@ span {
|
|
42
37
|
|
43
38
|
.row-bordered {
|
44
39
|
border: 1px solid #ddd;
|
45
|
-
}
|
40
|
+
}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
span {
|
2
|
+
font-family: "Helvetica Neue", Helvetica,"Arial Unicode MS", Arial, sans-serif;
|
3
|
+
}
|
4
|
+
|
5
|
+
.keyword {
|
6
|
+
color: #0000CC;
|
7
|
+
display: inline;
|
8
|
+
}
|
9
|
+
|
10
|
+
.schema,
|
11
|
+
.term {
|
12
|
+
/* Xcolor: #6A0072; The color used by NORMA */
|
13
|
+
color: #8A0092;
|
14
|
+
}
|
15
|
+
|
16
|
+
.schema:link, .schema:visited,
|
17
|
+
.term:link, .term:visited {
|
18
|
+
color: #8A0092; text-decoration: underline;
|
19
|
+
}
|
20
|
+
|
21
|
+
.reading {
|
22
|
+
color: #0E5400;
|
23
|
+
}
|
24
|
+
|
25
|
+
.value {
|
26
|
+
color: #FF990E;
|
27
|
+
display: inline;
|
28
|
+
}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
* {
|
2
|
+
margin: 0px;
|
3
|
+
padding: 0px;
|
4
|
+
}
|
5
|
+
|
6
|
+
ul, menu, dir {
|
7
|
+
display: block;
|
8
|
+
list-style-type: disc;
|
9
|
+
-webkit-margin-before: 0px;
|
10
|
+
-webkit-margin-after: 0px;
|
11
|
+
-webkit-margin-start: 0px;
|
12
|
+
-webkit-margin-end: 0px;
|
13
|
+
-webkit-padding-start: 0px;
|
14
|
+
}
|
15
|
+
li {
|
16
|
+
list-style: none;
|
17
|
+
}
|
18
|
+
|
@@ -0,0 +1,83 @@
|
|
1
|
+
/* Composition in the Treetable */
|
2
|
+
.mandatory {
|
3
|
+
font-weight: bold;
|
4
|
+
}
|
5
|
+
|
6
|
+
/* Treetable */
|
7
|
+
|
8
|
+
div.tt-outer { /* The wrapper for a Tree-Table structure */
|
9
|
+
line-height: 1.7em; /* Separate the lines by more than the height */
|
10
|
+
margin: 10px;
|
11
|
+
}
|
12
|
+
|
13
|
+
.tt-node { /* A node in a Tree-Table structure */
|
14
|
+
line-height: 1.5em;
|
15
|
+
background-color: #FFF; /* Make the message stand out from the background */
|
16
|
+
border: 3px ridge; /* A nice border around each node */
|
17
|
+
padding-left: 0.5em; /* Start text a bit further inside the border */
|
18
|
+
margin-left: 5px; /* Indent each node this much further */
|
19
|
+
margin-right: -3px; /* Overlay the right border of the outer object */
|
20
|
+
margin-bottom: -3px; /* Overlay the bottom border of the outer object */
|
21
|
+
}
|
22
|
+
|
23
|
+
.tt-list { /* A node for an array or list of items */
|
24
|
+
background: #DDF; /* Make it stand out by colour */
|
25
|
+
border: 4px ridge; /* Use a slightly fatter border */
|
26
|
+
margin-left: 1px; /* Stand a little further to the left than our peers */
|
27
|
+
margin-top: -3px; /* Stand a little to upwards */
|
28
|
+
margin-right: -3px; /* Bring the right margin to the left as well */
|
29
|
+
margin-bottom: 1px; /* Leave room below for the shadow to show */
|
30
|
+
box-shadow: 4px 4px 2px #888; /* Leave a shadow to the right and below */
|
31
|
+
}
|
32
|
+
|
33
|
+
.tt-list:before{
|
34
|
+
content:'(N) ';
|
35
|
+
font-size: 8pt;
|
36
|
+
vertical-align: top;
|
37
|
+
}
|
38
|
+
|
39
|
+
.tt-alt {
|
40
|
+
border-radius: 10px 10px 0px 10px; /* Use rounded corners */
|
41
|
+
margin-top: 10px; /* Leave a space above alternative items */
|
42
|
+
}
|
43
|
+
div:first-of-type.tt-alt {
|
44
|
+
margin-top: 0px !important; /* Don't leave a space above the first list item */
|
45
|
+
}
|
46
|
+
div:first-of-type.tt-alt:before {
|
47
|
+
content:'either';
|
48
|
+
font-size: 6pt;
|
49
|
+
}
|
50
|
+
|
51
|
+
.tt-alt:before{
|
52
|
+
content:'or';
|
53
|
+
font-size: 6pt;
|
54
|
+
}
|
55
|
+
|
56
|
+
.tt-desc { /* Display the data item description */
|
57
|
+
position: absolute; /* Glue it to the right of the outer block */
|
58
|
+
display: inline-block;
|
59
|
+
border-left: 3px ridge; /* Draw a vertical separator to the left */
|
60
|
+
background: #FFF; /* Ensure a long tt-type doesn't show through */
|
61
|
+
right: 11px; /* Fill the space to the far right, minus borders */
|
62
|
+
left: 36em; /* Start where the data type ends */
|
63
|
+
padding: 0px 5px 4px 5px; /* Leave room at the start and end */
|
64
|
+
line-height: 1.5em; /* Separate the lines by more than the height */
|
65
|
+
height: 1.3em; /* Clip the height to one line */
|
66
|
+
overflow: hidden; /* Don't attempt to show the whole text if it doesn't fit */
|
67
|
+
}
|
68
|
+
|
69
|
+
.tt-list > .tt-desc {
|
70
|
+
background: #DDF; /* Make it stand out by colour */
|
71
|
+
padding-bottom: 6px; /* -list has a bigger border, so the -desc needs to be taller */
|
72
|
+
}
|
73
|
+
.tt-type { /* Display the data type */
|
74
|
+
position: absolute; /* Glue it just left of the description */
|
75
|
+
display: inline-block;
|
76
|
+
border-left: 3px ridge; /* Draw a vertical separator to the left */
|
77
|
+
left: 24em; /* Start this far across */
|
78
|
+
width: 12em; /* Provide space for the type name */
|
79
|
+
padding: 0px 5px 0px 5px; /* Leave room at the start and end */
|
80
|
+
line-height: 1.5em; /* Separate the lines by more than the height */
|
81
|
+
height: 1.4em; /* Clip the height to one line */
|
82
|
+
overflow: hidden; /* Don't attempt to show the whole text if it doesn't fit */
|
83
|
+
}
|
@@ -15,26 +15,7 @@ require 'activefacts/support'
|
|
15
15
|
module ActiveFacts
|
16
16
|
module Generators
|
17
17
|
module Doc
|
18
|
-
|
19
|
-
# Add namespace id to metamodel forward referencing
|
20
|
-
class ActiveFacts::Metamodel::Composite # for tables
|
21
|
-
attr_accessor :xmiid
|
22
|
-
end
|
23
|
-
|
24
|
-
class ActiveFacts::Metamodel::Component # for columns
|
25
|
-
attr_accessor :xmiid
|
26
|
-
attr_accessor :index_xmiid
|
27
|
-
end
|
28
|
-
|
29
|
-
class ActiveFacts::Metamodel::Index # for primary and unique indexes
|
30
|
-
attr_accessor :xmiid
|
31
|
-
end
|
32
|
-
|
33
|
-
class ActiveFacts::Metamodel::ForeignKey # for foreign keys
|
34
|
-
attr_accessor :xmiid
|
35
|
-
end
|
36
|
-
|
37
|
-
class CWM
|
18
|
+
class CWM
|
38
19
|
MM = ActiveFacts::Metamodel unless const_defined?(:MM)
|
39
20
|
def self.options
|
40
21
|
{
|
@@ -42,7 +23,12 @@ module ActiveFacts
|
|
42
23
|
}
|
43
24
|
end
|
44
25
|
|
45
|
-
def
|
26
|
+
def self.compatibility
|
27
|
+
[1, %i{relational}] # one relational composition
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize constellation, composition, options = {}
|
31
|
+
@constellation = constellation
|
46
32
|
@composition = composition
|
47
33
|
@options = options
|
48
34
|
@underscore = options.has_key?("underscore") ? (options['underscore'] || '_') : ''
|
@@ -119,15 +105,15 @@ module ActiveFacts
|
|
119
105
|
def populate_namespace_ids
|
120
106
|
model_ns = rawnsdef
|
121
107
|
schema_ns = rawnsdef
|
122
|
-
|
108
|
+
|
123
109
|
@composition.
|
124
110
|
all_composite.
|
125
111
|
sort_by{|composite| composite.mapping.name}.
|
126
112
|
map{|composite| populate_table_ids(composite)}
|
127
|
-
|
113
|
+
|
128
114
|
[model_ns, schema_ns]
|
129
115
|
end
|
130
|
-
|
116
|
+
|
131
117
|
def populate_table_ids(table)
|
132
118
|
tname = table_name(table)
|
133
119
|
nsdef(table)
|
@@ -136,7 +122,7 @@ module ActiveFacts
|
|
136
122
|
next if leaf.is_a?(MM::Absorption) && leaf.parent_role.fact_type.is_a?(MM::TypeInheritance)
|
137
123
|
nsdef(leaf)
|
138
124
|
end
|
139
|
-
table.all_index.sort_by do |idx|
|
125
|
+
table.all_index.sort_by do |idx|
|
140
126
|
idx.all_index_field.map { |ixf| ixf.component.xmiid }
|
141
127
|
end.map do |index|
|
142
128
|
nsdef(index)
|
@@ -146,7 +132,7 @@ module ActiveFacts
|
|
146
132
|
nsdef(fk)
|
147
133
|
end
|
148
134
|
end
|
149
|
-
|
135
|
+
|
150
136
|
def generate_header
|
151
137
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
|
152
138
|
"<!DOCTYPE XMI SYSTEM \"CWM-1.1.dtd\">\n" +
|
@@ -167,11 +153,11 @@ module ActiveFacts
|
|
167
153
|
generate_data_types(2) +
|
168
154
|
" </XMI.content>\n"
|
169
155
|
end
|
170
|
-
|
156
|
+
|
171
157
|
def generate_footer
|
172
158
|
"</XMI>\n"
|
173
159
|
end
|
174
|
-
|
160
|
+
|
175
161
|
def generate_catalog(depth, model_ns, schema_ns)
|
176
162
|
catalog_start =
|
177
163
|
indent(depth, "<CWMRDB:Catalog xmi.id=\"#{model_ns}\" name=\"Model\" visibility=\"public\">") +
|
@@ -179,34 +165,34 @@ module ActiveFacts
|
|
179
165
|
indent(depth, " <CWMRDB:Schema xmi.id=\"#{schema_ns}\" name=\"Schema\" visibility=\"public\" namespace=\"#{model_ns}\">") +
|
180
166
|
indent(depth, " <CWM:Namespace.ownedElement>")
|
181
167
|
|
182
|
-
catalog_body =
|
168
|
+
catalog_body =
|
183
169
|
@composition.
|
184
170
|
all_composite.
|
185
171
|
sort_by{|composite| composite.mapping.name}.
|
186
172
|
map{|composite| generate_table(depth+4, schema_ns, composite)}*"\n" + "\n"
|
187
|
-
|
173
|
+
|
188
174
|
catalog_end =
|
189
175
|
indent(depth, " </CWM:Namespace.ownedElement>") +
|
190
176
|
indent(depth, " </CWMRDB:Schema>") +
|
191
177
|
indent(depth, " </CWM:Namespace.ownedElement>") +
|
192
178
|
indent(depth, "</CWMRDB:Catalog>")
|
193
|
-
|
179
|
+
|
194
180
|
catalog_start + catalog_body + catalog_end
|
195
181
|
end
|
196
|
-
|
182
|
+
|
197
183
|
def generate_data_types(depth)
|
198
184
|
@datatypes.map do | dt |
|
199
185
|
indent(depth, dt)
|
200
186
|
end * ""
|
201
187
|
end
|
202
|
-
|
188
|
+
|
203
189
|
def generate_table(depth, schema_ns, table)
|
204
190
|
name = table_name(table)
|
205
191
|
delayed_indices = []
|
206
|
-
|
192
|
+
|
207
193
|
table_start =
|
208
194
|
indent(depth, "<CWMRDB:Table xmi.id=\"#{table.xmiid}\" name=\"#{name}\" isSystem=\"false\" isTemporary=\"false\" visibility=\"public\" namespace=\"#{schema_ns}\">")
|
209
|
-
|
195
|
+
|
210
196
|
table_columns =
|
211
197
|
indent(depth, " <CWM:Classifier.feature>") +
|
212
198
|
(table.mapping.all_leaf.flat_map.sort_by{|c| column_name(c)}.map do |leaf|
|
@@ -220,7 +206,7 @@ module ActiveFacts
|
|
220
206
|
|
221
207
|
table_keys =
|
222
208
|
indent(depth, " <CWM:Namespace.ownedElement>") +
|
223
|
-
(table.all_index.sort_by do |idx|
|
209
|
+
(table.all_index.sort_by do |idx|
|
224
210
|
idx.all_index_field.map { |ixf| ixf.component.xmiid }
|
225
211
|
end.map do |index|
|
226
212
|
generate_index(depth+2, table.xmiid, index, name, table.all_foreign_key_as_target_composite)
|
@@ -231,23 +217,23 @@ module ActiveFacts
|
|
231
217
|
end
|
232
218
|
) * "" +
|
233
219
|
indent(depth, " </CWM:Namespace.ownedElement>")
|
234
|
-
|
220
|
+
|
235
221
|
table_end =
|
236
222
|
indent(depth, "</CWMRDB:Table>")
|
237
|
-
|
223
|
+
|
238
224
|
table_start + table_columns + table_keys + table_end
|
239
225
|
end
|
240
226
|
|
241
227
|
def generate_column(depth, table_ns, column)
|
242
228
|
name = safe_column_name(column)
|
243
|
-
|
229
|
+
|
244
230
|
is_nullable = column.path_mandatory ? "columnNoNulls" : "columnNullable"
|
245
231
|
constraints = column.all_leaf_constraint
|
246
232
|
|
247
233
|
type_name, options = column.data_type(data_type_context)
|
248
234
|
options ||= {}
|
249
235
|
length = options[:length]
|
250
|
-
|
236
|
+
|
251
237
|
type_name, type_num = normalise_type_cwm(type_name, length)
|
252
238
|
column_params = ""
|
253
239
|
type_params = ""
|
@@ -259,14 +245,14 @@ module ActiveFacts
|
|
259
245
|
|
260
246
|
def create_data_type(type_name, type_num, type_params)
|
261
247
|
type_ns = rawnsdef
|
262
|
-
|
263
|
-
cwm_data_type =
|
248
|
+
|
249
|
+
cwm_data_type =
|
264
250
|
"<CWMRDB:SQLSimpleType xmi.id=\"#{type_ns}\" name=\"#{type_name}\" visibility=\"public\" typeNumber=\"#{type_num}\" #{type_params}/>"
|
265
|
-
|
251
|
+
|
266
252
|
@datatypes << cwm_data_type
|
267
253
|
type_ns
|
268
254
|
end
|
269
|
-
|
255
|
+
|
270
256
|
def generate_index(depth, table_ns, index, table_name, all_fks_as_target)
|
271
257
|
key_ns = index.xmiid
|
272
258
|
|
@@ -285,7 +271,7 @@ module ActiveFacts
|
|
285
271
|
# (index.composite_as_primary_index ? ' CLUSTERED' : ' NONCLUSTERED')
|
286
272
|
|
287
273
|
key_type = primary ? 'CWMRDB:PrimaryKey' : 'CWM:UniqueKey'
|
288
|
-
|
274
|
+
|
289
275
|
# find target foreign keys for this index
|
290
276
|
fks_as_target = all_fks_as_target
|
291
277
|
|
@@ -307,7 +293,7 @@ module ActiveFacts
|
|
307
293
|
if fks_as_target.count > 0
|
308
294
|
indent(depth, "<CWM:UniqueKey.keyRelationship>") +
|
309
295
|
fks_as_target.map do |fk|
|
310
|
-
indent(depth, " <CWM:KeyRelationship xmi.idref=\"#{fk.xmiid}\"/>")
|
296
|
+
indent(depth, " <CWM:KeyRelationship xmi.idref=\"#{fk.xmiid}\"/>")
|
311
297
|
end * "" +
|
312
298
|
indent(depth, "</CWM:UniqueKey.keyRelationship>")
|
313
299
|
else
|
@@ -316,10 +302,10 @@ module ActiveFacts
|
|
316
302
|
indent(depth, "</#{key_type}>")
|
317
303
|
end
|
318
304
|
end
|
319
|
-
|
305
|
+
|
320
306
|
def generate_foreign_key(depth, table_ns, fk)
|
321
307
|
key_ns = fk.xmiid
|
322
|
-
|
308
|
+
|
323
309
|
if fk.all_foreign_key_field.size == 1
|
324
310
|
fkf = fk.all_foreign_key_field[0]
|
325
311
|
ixf = fk.all_index_field[0]
|
@@ -335,16 +321,16 @@ module ActiveFacts
|
|
335
321
|
out += indent(depth, " <CWM:StructuralFeature xmi.idref=\"#{fkf.component.xmiid}\" uniqueKey=\"#{ixf.component.index_xmiid}\" />")
|
336
322
|
end
|
337
323
|
out
|
338
|
-
end +
|
324
|
+
end +
|
339
325
|
indent(depth, " </CWM:KeyRelationship.feature>") +
|
340
326
|
indent(depth, "</CWMRDB:ForeignKey>")
|
341
327
|
end
|
342
328
|
# fk.all_foreign_key_field.map{|fkf| safe_column_name fkf.component}*", " +
|
343
329
|
# ") REFERENCES #{safe_table_name fk.composite} (" +
|
344
330
|
# fk.all_index_field.map{|ixf| safe_column_name ixf.component}*", " +
|
345
|
-
|
331
|
+
|
346
332
|
# indent(depth, "<CWMRDB:ForeignKey xmi.id=\"#{key_ns}\" name=\"R#{key_ns}\" visibility=\"public\" namespace=\"#{ns}\" feature=\"_41\" uniqueKey=\"_48\" deleteRule=\"importedKeyRestrict\" updateRule=\"importedKeyRestrict\"/>")
|
347
|
-
|
333
|
+
|
348
334
|
end
|
349
335
|
|
350
336
|
def boolean_type
|
@@ -426,8 +412,8 @@ module ActiveFacts
|
|
426
412
|
['int', 4]
|
427
413
|
end
|
428
414
|
end
|
429
|
-
|
430
|
-
|
415
|
+
|
416
|
+
|
431
417
|
def sql_value(value)
|
432
418
|
value.is_literal_string ? sql_string(value.literal) : value.literal
|
433
419
|
end
|
@@ -516,9 +502,29 @@ module ActiveFacts
|
|
516
502
|
default_varchar_type
|
517
503
|
end
|
518
504
|
end
|
519
|
-
|
505
|
+
|
520
506
|
end
|
521
507
|
end
|
522
508
|
publish_generator Doc::CWM, "Common Warehouse Metamodel represented as an XMI file. Use a relational compositor"
|
523
509
|
end
|
510
|
+
|
511
|
+
module Metamodel
|
512
|
+
# Add namespace id to metamodel forward referencing
|
513
|
+
class Composite # for tables
|
514
|
+
attr_accessor :xmiid
|
515
|
+
end
|
516
|
+
|
517
|
+
class Component # for columns
|
518
|
+
attr_accessor :xmiid
|
519
|
+
attr_accessor :index_xmiid
|
520
|
+
end
|
521
|
+
|
522
|
+
class Index # for primary and unique indexes
|
523
|
+
attr_accessor :xmiid
|
524
|
+
end
|
525
|
+
|
526
|
+
class ForeignKey # for foreign keys
|
527
|
+
attr_accessor :xmiid
|
528
|
+
end
|
529
|
+
end
|
524
530
|
end
|