activefacts-compositions 1.9.10 → 1.9.12
Sign up to get free protection for your applications and to get access to all the features.
- 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
|