activefacts-compositions 1.9.10 → 1.9.12
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 +4 -4
- data/.gitignore +1 -0
- data/activefacts-compositions.gemspec +6 -5
- data/bin/afcomp +192 -0
- data/bin/schema_compositor +26 -11
- data/lib/activefacts/compositions/binary.rb +4 -0
- data/lib/activefacts/compositions/compositor.rb +79 -7
- data/lib/activefacts/compositions/datavault.rb +308 -110
- data/lib/activefacts/compositions/docgraph.rb +798 -0
- data/lib/activefacts/compositions/relational.rb +8 -8
- data/lib/activefacts/compositions/staging.rb +3 -2
- data/lib/activefacts/compositions/version.rb +1 -1
- data/lib/activefacts/generator/doc/cwm.rb +11 -17
- data/lib/activefacts/generator/oo.rb +2 -3
- data/lib/activefacts/generator/rails/models.rb +2 -3
- data/lib/activefacts/generator/rails/schema.rb +2 -3
- data/lib/activefacts/generator/ruby.rb +1 -2
- data/lib/activefacts/generator/sql.rb +29 -15
- data/lib/activefacts/generator/summary.rb +22 -17
- data/lib/activefacts/generator/transgen.rb +144 -0
- data/lib/activefacts/generator/validate.rb +3 -3
- metadata +59 -21
@@ -14,14 +14,14 @@ module ActiveFacts
|
|
14
14
|
|
15
15
|
def self.options
|
16
16
|
{
|
17
|
-
surrogates: ['Boolean', "Inject a surrogate key into each table whose primary key is not already suitable as a foreign key"]
|
18
|
-
}
|
17
|
+
surrogates: ['Boolean', "Inject a surrogate key into each table whose primary key is not already suitable as a foreign key"],
|
18
|
+
}.merge(Compositor.options)
|
19
19
|
end
|
20
20
|
|
21
|
-
def initialize constellation, name, options = {}
|
21
|
+
def initialize constellation, name, options = {}, compositor_name = 'Relational'
|
22
22
|
# Extract recognised options:
|
23
23
|
@option_surrogates = options.delete('surrogates')
|
24
|
-
super constellation, name, options
|
24
|
+
super constellation, name, options, compositor_name
|
25
25
|
end
|
26
26
|
|
27
27
|
def generate
|
@@ -183,10 +183,10 @@ module ActiveFacts
|
|
183
183
|
next true if a.full_absorption && child_candidate.full_absorption.absorption != a
|
184
184
|
|
185
185
|
# If our counterpart is a full absorption, don't try to reverse that!
|
186
|
-
next false if (a.forward_absorption || a.reverse_absorption).full_absorption
|
186
|
+
next false if (aa = (a.forward_absorption || a.reverse_absorption)) && aa.full_absorption
|
187
187
|
|
188
188
|
# Otherwise the other end must already be a table or fully absorbed into one
|
189
|
-
next false unless child_candidate.is_table || child_candidate.full_absorption
|
189
|
+
next false unless child_candidate.nil? || child_candidate.is_table || child_candidate.full_absorption
|
190
190
|
|
191
191
|
next false unless a.child_role.is_unique && a.parent_role.is_unique # Must be one-to-one
|
192
192
|
|
@@ -347,7 +347,7 @@ module ActiveFacts
|
|
347
347
|
# * there are no other columns (that might require updating) and
|
348
348
|
# * the object is not the target of a foreign key:
|
349
349
|
if non_fk_surrogate
|
350
|
-
trace :surrogates, "#{composite.inspect} has non-FK identifiers so requires a surrogate"
|
350
|
+
trace :surrogates, "#{composite.inspect} has non-FK identifiers (in #{key_members.inspect}) so requires a surrogate"
|
351
351
|
return true
|
352
352
|
end
|
353
353
|
|
@@ -389,7 +389,7 @@ module ActiveFacts
|
|
389
389
|
trace :surrogates, "#{composite.inspect} already has an auto-assigned key so does NOT require a surrogate"
|
390
390
|
return false
|
391
391
|
end
|
392
|
-
trace :surrogates, "#{composite.inspect} requires a surrogate"
|
392
|
+
trace :surrogates, "#{composite.inspect} PK is #{key_member.inspect} which requires a surrogate"
|
393
393
|
return true
|
394
394
|
end
|
395
395
|
|
@@ -14,7 +14,8 @@ module ActiveFacts
|
|
14
14
|
def self.options
|
15
15
|
{
|
16
16
|
stgname: ['String', "Suffix or pattern for naming staging tables. Include a + to insert the name. Default 'STG'"],
|
17
|
-
}
|
17
|
+
}.merge(Relational.options).
|
18
|
+
reject{|k,v| [:surrogates].include?(k) }
|
18
19
|
end
|
19
20
|
|
20
21
|
def initialize constellation, name, options = {}
|
@@ -22,7 +23,7 @@ module ActiveFacts
|
|
22
23
|
@option_stg_name = options.delete('stgname') || 'STG'
|
23
24
|
@option_stg_name.sub!(/^/,'+ ') unless @option_stg_name =~ /\+/
|
24
25
|
|
25
|
-
super constellation, name, options
|
26
|
+
super constellation, name, options, 'Staging'
|
26
27
|
|
27
28
|
end
|
28
29
|
|
@@ -21,15 +21,11 @@ module ActiveFacts
|
|
21
21
|
attr_accessor :xmiid
|
22
22
|
end
|
23
23
|
|
24
|
-
class ActiveFacts::Metamodel::
|
24
|
+
class ActiveFacts::Metamodel::Component # for columns
|
25
25
|
attr_accessor :xmiid
|
26
26
|
attr_accessor :index_xmiid
|
27
27
|
end
|
28
28
|
|
29
|
-
class ActiveFacts::Metamodel::Indicator
|
30
|
-
attr_accessor :xmiid
|
31
|
-
end
|
32
|
-
|
33
29
|
class ActiveFacts::Metamodel::Index # for primary and unique indexes
|
34
30
|
attr_accessor :xmiid
|
35
31
|
end
|
@@ -38,11 +34,6 @@ module ActiveFacts
|
|
38
34
|
attr_accessor :xmiid
|
39
35
|
end
|
40
36
|
|
41
|
-
class ActiveFacts::Metamodel::ValueField
|
42
|
-
attr_accessor :xmiid
|
43
|
-
attr_accessor :index_xmiid
|
44
|
-
end
|
45
|
-
|
46
37
|
class CWM
|
47
38
|
MM = ActiveFacts::Metamodel unless const_defined?(:MM)
|
48
39
|
def self.options
|
@@ -51,9 +42,8 @@ module ActiveFacts
|
|
51
42
|
}
|
52
43
|
end
|
53
44
|
|
54
|
-
def initialize
|
55
|
-
|
56
|
-
@composition = compositions[0]
|
45
|
+
def initialize composition, options = {}
|
46
|
+
@composition = composition
|
57
47
|
@options = options
|
58
48
|
@underscore = options.has_key?("underscore") ? (options['underscore'] || '_') : ''
|
59
49
|
|
@@ -141,12 +131,14 @@ module ActiveFacts
|
|
141
131
|
def populate_table_ids(table)
|
142
132
|
tname = table_name(table)
|
143
133
|
nsdef(table)
|
144
|
-
table.mapping.all_leaf.flat_map do |leaf|
|
134
|
+
table.mapping.all_leaf.flat_map.sort_by{|c| column_name(c)}.map do |leaf|
|
145
135
|
# Absorbed empty subtypes appear as leaves
|
146
136
|
next if leaf.is_a?(MM::Absorption) && leaf.parent_role.fact_type.is_a?(MM::TypeInheritance)
|
147
137
|
nsdef(leaf)
|
148
138
|
end
|
149
|
-
table.all_index.
|
139
|
+
table.all_index.sort_by do |idx|
|
140
|
+
idx.all_index_field.map { |ixf| ixf.component.xmiid }
|
141
|
+
end.map do |index|
|
150
142
|
nsdef(index)
|
151
143
|
index.all_index_field.map{|idf| idf.component.index_xmiid = index.xmiid}
|
152
144
|
end
|
@@ -162,7 +154,7 @@ module ActiveFacts
|
|
162
154
|
"<XMI xmlns:CWM=\"org.omg.CWM1.1\" xmlns:CWMRDB=\"org.omg.CWM1.1/Relational\" xmi.version=\"1.1\">\n" +
|
163
155
|
" <XMI.header>\n" +
|
164
156
|
" <XMI.documentation>\n" +
|
165
|
-
" <XMI.exporter>
|
157
|
+
" <XMI.exporter>ActiveFacts</XMI.exporter>\n" +
|
166
158
|
" <XMI.exporterVersion>0.1</XMI.exporterVersion>\n" +
|
167
159
|
" </XMI.documentation>\n" +
|
168
160
|
" <XMI.metamodel xmi.name=\"CWM\" xmi.version=\"1.1\" />" +
|
@@ -228,7 +220,9 @@ module ActiveFacts
|
|
228
220
|
|
229
221
|
table_keys =
|
230
222
|
indent(depth, " <CWM:Namespace.ownedElement>") +
|
231
|
-
|
223
|
+
(table.all_index.sort_by do |idx|
|
224
|
+
idx.all_index_field.map { |ixf| ixf.component.xmiid }
|
225
|
+
end.map do |index|
|
232
226
|
generate_index(depth+2, table.xmiid, index, name, table.all_foreign_key_as_target_composite)
|
233
227
|
end
|
234
228
|
) * "" +
|
@@ -18,9 +18,8 @@ module ActiveFacts
|
|
18
18
|
}
|
19
19
|
end
|
20
20
|
|
21
|
-
def initialize
|
22
|
-
|
23
|
-
@composition = compositions[0]
|
21
|
+
def initialize composition, options = {}
|
22
|
+
@composition = composition
|
24
23
|
@options = options
|
25
24
|
@comments = @options.delete("comments")
|
26
25
|
end
|
@@ -22,9 +22,8 @@ module ActiveFacts
|
|
22
22
|
})
|
23
23
|
end
|
24
24
|
|
25
|
-
def initialize
|
26
|
-
|
27
|
-
@composition = compositions[0]
|
25
|
+
def initialize composition, options = {}
|
26
|
+
@composition = composition
|
28
27
|
@options = options
|
29
28
|
@option_output = options.delete("output")
|
30
29
|
@option_concern = options.delete("concern")
|
@@ -24,9 +24,8 @@ module ActiveFacts
|
|
24
24
|
})
|
25
25
|
end
|
26
26
|
|
27
|
-
def initialize
|
28
|
-
|
29
|
-
@composition = compositions[0]
|
27
|
+
def initialize composition, options = {}
|
28
|
+
@composition = composition
|
30
29
|
@options = options
|
31
30
|
@option_exclude_fks = options.delete("exclude_fks")
|
32
31
|
@option_include_comments = options.delete("include_comments")
|
@@ -20,8 +20,7 @@ module ActiveFacts
|
|
20
20
|
)
|
21
21
|
end
|
22
22
|
|
23
|
-
def initialize
|
24
|
-
raise "--ruby only processes a single composition" if compositions.size > 1
|
23
|
+
def initialize composition, options = {}
|
25
24
|
super
|
26
25
|
@scope = options.delete('scope') || ''
|
27
26
|
@scope = @scope.split(/::/)
|
@@ -14,35 +14,47 @@ module ActiveFacts
|
|
14
14
|
module Generators
|
15
15
|
# Options are comma or space separated:
|
16
16
|
# * delay_fks Leave all foreign keys until the end, not just those that contain forward-references
|
17
|
-
# * underscore
|
17
|
+
# * underscore
|
18
18
|
class SQL
|
19
19
|
MM = ActiveFacts::Metamodel unless const_defined?(:MM)
|
20
20
|
def self.options
|
21
21
|
{
|
22
22
|
delay_fks: ['Boolean', "Delay emitting all foreign keys until the bottom of the file"],
|
23
|
-
underscore: [String, "Use 'str' instead of underscore between words in table names"],
|
23
|
+
underscore: ['String', "Use 'str' instead of underscore between words in table names"],
|
24
24
|
unicode: ['Boolean', "Use Unicode for all text fields by default"],
|
25
|
+
# datavault: ['String', "Generate 'raw' or 'business' data vault tables"],
|
26
|
+
restrict: ['String', "Restrict generation to tables in the specified group (e.g. bdv, rdv)"]
|
25
27
|
}
|
26
28
|
end
|
27
29
|
|
28
|
-
def initialize
|
29
|
-
|
30
|
-
@composition = compositions[0]
|
30
|
+
def initialize composition, options = {}
|
31
|
+
@composition = composition
|
31
32
|
@options = options
|
32
33
|
@delay_fks = options.delete "delay_fks"
|
33
34
|
@underscore = options.has_key?("underscore") ? (options['underscore'] || '_') : ''
|
34
35
|
@unicode = options.delete "unicode"
|
36
|
+
@restrict = options.delete "restrict"
|
37
|
+
# Legacy option. Use restrict=bdv/rdv instead
|
38
|
+
@datavault = options.delete "datavault"
|
39
|
+
case @datavault
|
40
|
+
when "business"
|
41
|
+
@restrict = "bdv"
|
42
|
+
when "raw"
|
43
|
+
@restrict = "rdv"
|
44
|
+
end
|
35
45
|
end
|
36
46
|
|
37
47
|
def generate
|
38
48
|
@tables_emitted = {}
|
39
49
|
@delayed_foreign_keys = []
|
40
50
|
|
51
|
+
@composite_list = @composition.all_composite.sort_by{|composite| composite.mapping.name}
|
52
|
+
if @restrict
|
53
|
+
@composite_list.select!{|composite| g = composite.composite_group and g.name == @restrict}
|
54
|
+
end
|
55
|
+
|
41
56
|
generate_schema +
|
42
|
-
@
|
43
|
-
all_composite.
|
44
|
-
sort_by{|composite| composite.mapping.name}.
|
45
|
-
map{|composite| generate_table composite}*"\n" + "\n" +
|
57
|
+
@composite_list.map{|composite| generate_table composite}*"\n" + "\n" +
|
46
58
|
@delayed_foreign_keys.sort*"\n"
|
47
59
|
end
|
48
60
|
|
@@ -88,7 +100,9 @@ module ActiveFacts
|
|
88
100
|
end.compact.sort +
|
89
101
|
composite.all_foreign_key_as_source_composite.map do |fk|
|
90
102
|
fk_text = generate_foreign_key fk
|
91
|
-
if !@delay_fks and
|
103
|
+
if !@delay_fks and # We're not delaying foreign keys unnecessarily
|
104
|
+
@tables_emitted[fk.composite] || # Already done
|
105
|
+
!@composite_list.include?(fk.composite) # Not going to be done
|
92
106
|
fk_text
|
93
107
|
else
|
94
108
|
@delayed_foreign_keys <<
|
@@ -195,12 +209,12 @@ module ActiveFacts
|
|
195
209
|
MM::DataType.normalise_int_length('int', data_type_context.default_surrogate_length, value_constraint, data_type_context)[0]
|
196
210
|
else
|
197
211
|
v, = MM::DataType.normalise_int_length(type_name, length, value_constraint, data_type_context)
|
198
|
-
v
|
212
|
+
v # The typename here has the appropriate length, don't return a length
|
199
213
|
end
|
200
214
|
when MM::DataType::TYPE_Real;
|
201
215
|
["FLOAT", data_type_context.default_length(type, type_name)]
|
202
|
-
when MM::DataType::TYPE_Decimal; 'DECIMAL'
|
203
|
-
when MM::DataType::TYPE_Money; 'DECIMAL'
|
216
|
+
when MM::DataType::TYPE_Decimal; ['DECIMAL', length]
|
217
|
+
when MM::DataType::TYPE_Money; ['DECIMAL', length]
|
204
218
|
when MM::DataType::TYPE_Char; [data_type_context.default_char_type, length || data_type_context.char_default_length]
|
205
219
|
when MM::DataType::TYPE_String; [data_type_context.default_varchar_type, length || data_type_context.varchar_default_length]
|
206
220
|
when MM::DataType::TYPE_Text; [data_type_context.default_text_type, length || 'MAX']
|
@@ -213,10 +227,10 @@ module ActiveFacts
|
|
213
227
|
if length
|
214
228
|
['BINARY', length]
|
215
229
|
else
|
216
|
-
'VARBINARY'
|
230
|
+
['VARBINARY', length]
|
217
231
|
end
|
218
232
|
else
|
219
|
-
type_name
|
233
|
+
[type_name, length]
|
220
234
|
end
|
221
235
|
end
|
222
236
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#
|
2
2
|
# ActiveFacts Compositions, Metamodel aspect to create a textual summary of a composition and its Composites
|
3
|
-
#
|
3
|
+
#
|
4
4
|
# Copyright (c) 2015 Clifford Heath. Read the LICENSE file.
|
5
5
|
#
|
6
6
|
require "activefacts/metamodel"
|
@@ -13,7 +13,11 @@ module ActiveFacts
|
|
13
13
|
class Composition
|
14
14
|
def summary
|
15
15
|
classify_constraints
|
16
|
-
|
16
|
+
|
17
|
+
vn = (v = constellation.Vocabulary.values[0]) ? v.version_number : nil
|
18
|
+
version_str = vn ? " version #{vn}" : ''
|
19
|
+
|
20
|
+
"Summary of #{name}#{version_str}\n" +
|
17
21
|
all_composite.
|
18
22
|
sort_by{|composite| composite.mapping.name}.
|
19
23
|
flat_map do |composite|
|
@@ -35,14 +39,15 @@ module ActiveFacts
|
|
35
39
|
|
36
40
|
# Build a display of the names in this absorption path, with FK and optional indicators
|
37
41
|
path_names = leaf.path.map do |component|
|
38
|
-
is_mandatory =
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
is_mandatory = true
|
43
|
+
is_unique = true
|
44
|
+
case component
|
45
|
+
when Absorption
|
46
|
+
is_mandatory = component.parent_role.is_mandatory
|
47
|
+
is_unique = component.parent_role.is_unique
|
48
|
+
when Indicator
|
49
|
+
is_mandatory = false
|
50
|
+
end
|
46
51
|
|
47
52
|
if component.all_foreign_key_field.size > 0
|
48
53
|
"[#{component.name}]"
|
@@ -51,8 +56,8 @@ module ActiveFacts
|
|
51
56
|
else
|
52
57
|
component.name
|
53
58
|
end +
|
54
|
-
(is_mandatory ? '' : '?')
|
55
|
-
end*'->'
|
59
|
+
(is_mandatory ? '' : '?') + (is_unique ? '' : '*')
|
60
|
+
end*'->'
|
56
61
|
|
57
62
|
# Build a symbolic representation of the index participation of this leaf
|
58
63
|
pos = 0
|
@@ -63,8 +68,8 @@ module ActiveFacts
|
|
63
68
|
end
|
64
69
|
a
|
65
70
|
end
|
66
|
-
if indexing.empty?
|
67
|
-
indexing = ''
|
71
|
+
if indexing.empty?
|
72
|
+
indexing = ''
|
68
73
|
else
|
69
74
|
indexing = "[#{indexing*','}]"
|
70
75
|
end
|
@@ -92,13 +97,13 @@ module ActiveFacts
|
|
92
97
|
}
|
93
98
|
end
|
94
99
|
|
95
|
-
def initialize
|
96
|
-
@
|
100
|
+
def initialize composition, options = {}
|
101
|
+
@composition = composition
|
97
102
|
@options = options
|
98
103
|
end
|
99
104
|
|
100
105
|
def generate
|
101
|
-
@
|
106
|
+
@composition.summary
|
102
107
|
end
|
103
108
|
end
|
104
109
|
publish_generator Summary
|
@@ -0,0 +1,144 @@
|
|
1
|
+
#
|
2
|
+
# ActiveFacts Tranformation Rule Stub Generator
|
3
|
+
#
|
4
|
+
# Copyright (c) 2017 Factil Pty Ltd. Read the LICENSE file.
|
5
|
+
#
|
6
|
+
require 'digest/sha1'
|
7
|
+
require 'activefacts/metamodel'
|
8
|
+
require 'activefacts/metamodel/datatypes'
|
9
|
+
require 'activefacts/compositions'
|
10
|
+
require 'activefacts/compositions/names'
|
11
|
+
require 'activefacts/generator'
|
12
|
+
|
13
|
+
module ActiveFacts
|
14
|
+
module Generators
|
15
|
+
class TransGen
|
16
|
+
INDENT = " "
|
17
|
+
def self.options
|
18
|
+
{
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize composition, options = {}
|
23
|
+
@composition = composition
|
24
|
+
@options = options
|
25
|
+
end
|
26
|
+
|
27
|
+
def generate
|
28
|
+
@constellation = @composition.constellation
|
29
|
+
@transform_topic = @constellation.Topic.values.select{|t| t.all_import_as_precursor_topic.size == 0}.first
|
30
|
+
if !@constellation.Vocabulary.values.to_a[0].is_transform
|
31
|
+
raise "Expected input file to be transform"
|
32
|
+
end
|
33
|
+
|
34
|
+
source_imports = @constellation.Import.values.select{|imp| imp.topic == @transform_topic && imp.import_role == "source"}
|
35
|
+
target_imports = @constellation.Import.values.select{|imp| imp.topic == @transform_topic && imp.import_role == "target"}
|
36
|
+
|
37
|
+
composite_list = @composition.all_composite.select do |composite|
|
38
|
+
target_imports.detect do |imp|
|
39
|
+
imp.precursor_topic.all_concept.detect{|c| c.object_type == composite.mapping.object_type}
|
40
|
+
end
|
41
|
+
end.sort_by{|composite| composite.mapping.name}
|
42
|
+
|
43
|
+
generate_header(source_imports, target_imports) +
|
44
|
+
composite_list.map{|composite| generate_transform_rule composite}*"\n" + "\n"
|
45
|
+
end
|
46
|
+
|
47
|
+
def generate_header source_imports, target_imports
|
48
|
+
"transform #{@transform_topic.topic_name};\n" +
|
49
|
+
"\n" +
|
50
|
+
source_imports.map{|imp| "import source #{imp.precursor_topic.topic_name};"} * "\n" + "\n" +
|
51
|
+
target_imports.map{|imp| "import target #{imp.precursor_topic.topic_name};"} * "\n" + "\n" +
|
52
|
+
"\n"
|
53
|
+
end
|
54
|
+
|
55
|
+
def generate_transform_rule composite
|
56
|
+
existing_rules = @transform_topic.all_concept.select do |concept|
|
57
|
+
tr = concept.transform_rule and
|
58
|
+
tr.compound_matching.all_transform_target_ref.to_a[0].object_type == composite.mapping.object_type
|
59
|
+
end.map {|concept| concept.transform_rule}
|
60
|
+
|
61
|
+
if existing_rules.size > 0
|
62
|
+
existing_rules.map{|tr| regenerate_transform_rule(composite, tr)} * "\n\n"
|
63
|
+
else
|
64
|
+
generate_new_transform_rule(composite)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def indent text, level
|
69
|
+
INDENT * level + text
|
70
|
+
end
|
71
|
+
|
72
|
+
def leading_hyphenate leading_adjective
|
73
|
+
words = leading_adjective.words
|
74
|
+
if words.size == 1
|
75
|
+
leading_adjective + '-'
|
76
|
+
else
|
77
|
+
words[0] + '- ' + words[1..-1].join(' ')
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def trailing_hyphenate trailing_adjective
|
82
|
+
words = trailing_adjective.words
|
83
|
+
if words.size == 1
|
84
|
+
'-' + trailing_adjective
|
85
|
+
else
|
86
|
+
words[0...-1].join(' ') + ' -' + words[-1]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def full_role_name mapping
|
91
|
+
if mapping.is_a?(ActiveFacts::Metamodel::Absorption)
|
92
|
+
la = mapping.child_role.all_role_ref.to_a[0].leading_adjective
|
93
|
+
ta = mapping.child_role.all_role_ref.to_a[0].trailing_adjective
|
94
|
+
(la ? leading_hyphenate(la) + ' ' : '') + mapping.object_type.name + (ta ? ' ' + trailing_hyphenate(ta) : '')
|
95
|
+
else
|
96
|
+
mapping.object_type.name
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# New transform rule
|
102
|
+
#
|
103
|
+
def generate_new_transform_rule composite
|
104
|
+
generate_compound_matching(composite.mapping, 0, '') + ";\n"
|
105
|
+
end
|
106
|
+
|
107
|
+
def generate_transform_matching mapping, level, prefix
|
108
|
+
if mapping.object_type.is_a?(ActiveFacts::Metamodel::ValueType)
|
109
|
+
generate_simple_matching(mapping, level, prefix)
|
110
|
+
else
|
111
|
+
generate_compound_matching(mapping, level, prefix)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def generate_simple_matching mapping, level, prefix
|
116
|
+
full_name = full_role_name(mapping)
|
117
|
+
prefixed_name = (prefix.size > 0 ? prefix + ' . ' : '') + full_name
|
118
|
+
indent("#{prefixed_name} <-- /* EXPR */", level)
|
119
|
+
end
|
120
|
+
|
121
|
+
def generate_compound_matching mapping, level, prefix
|
122
|
+
members = mapping.all_member.sort_by(&:ordinal).flatten
|
123
|
+
prefixed_name = (prefix.size > 0 ? prefix + ' . ' : '') + full_role_name(mapping)
|
124
|
+
if members.size == 1
|
125
|
+
generate_transform_matching(members[0], level, prefixed_name)
|
126
|
+
else
|
127
|
+
indent("#{prefixed_name} <== /* OBJECT TYPE or QUERY */ {\n", level) +
|
128
|
+
members.map do |m|
|
129
|
+
generate_transform_matching(m, level + 1, '')
|
130
|
+
end * ",\n" + "\n" +
|
131
|
+
indent("}", level)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
#
|
136
|
+
# Regenerate existing transform rule
|
137
|
+
#
|
138
|
+
def regenerate_transform_rule(composite, transform_rule)
|
139
|
+
# regenerate_compound_matching(composite.mapping, 0, '') + ";\n"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
publish_generator TransGen
|
143
|
+
end
|
144
|
+
end
|