activefacts-generators 1.8.3 → 1.9.0
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/activefacts-generators.gemspec +3 -3
- data/lib/activefacts/dependency_analyser.rb +80 -80
- data/lib/activefacts/generators/absorption.rb +1 -1
- data/lib/activefacts/generators/composition.rb +76 -76
- data/lib/activefacts/generators/cql.rb +73 -73
- data/lib/activefacts/generators/diagrams/json.rb +313 -313
- data/lib/activefacts/generators/help.rb +10 -10
- data/lib/activefacts/generators/helpers/inject.rb +5 -5
- data/lib/activefacts/generators/helpers/oo.rb +5 -5
- data/lib/activefacts/generators/helpers/ordered.rb +51 -51
- data/lib/activefacts/generators/html/glossary.rb +241 -241
- data/lib/activefacts/generators/metadata/json.rb +155 -155
- data/lib/activefacts/generators/ruby.rb +4 -4
- data/lib/activefacts/generators/scala.rb +48 -48
- data/lib/activefacts/generators/sql/server.rb +3 -3
- data/lib/activefacts/generators/stats.rb +37 -37
- data/lib/activefacts/generators/traits/datavault.rb +217 -217
- data/lib/activefacts/generators/traits/oo.rb +13 -13
- data/lib/activefacts/generators/traits/ordered.rb +8 -8
- data/lib/activefacts/generators/traits/ruby.rb +145 -145
- data/lib/activefacts/generators/traits/scala.rb +319 -319
- data/lib/activefacts/generators/transform/datavault.rb +282 -282
- metadata +6 -12
@@ -18,7 +18,7 @@ module ActiveFacts
|
|
18
18
|
private
|
19
19
|
def vocabulary_start
|
20
20
|
puts "vocabulary #{@vocabulary.name};\n\n"
|
21
|
-
|
21
|
+
build_indices
|
22
22
|
end
|
23
23
|
|
24
24
|
def vocabulary_end
|
@@ -29,7 +29,7 @@ module ActiveFacts
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def unit_dump unit
|
32
|
-
|
32
|
+
puts unit.as_cql
|
33
33
|
end
|
34
34
|
|
35
35
|
def units_end
|
@@ -45,7 +45,7 @@ module ActiveFacts
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def data_type_dump(o)
|
48
|
-
|
48
|
+
value_type_dump(o, o.name, {}) if o.all_role.size > 0
|
49
49
|
end
|
50
50
|
|
51
51
|
def value_type_dump(o, super_type_name, facets)
|
@@ -54,22 +54,22 @@ module ActiveFacts
|
|
54
54
|
|
55
55
|
# REVISIT: A ValueType that is only used as a reference mode need not be emitted here.
|
56
56
|
|
57
|
-
|
57
|
+
puts o.as_cql
|
58
58
|
end
|
59
59
|
|
60
60
|
def entity_type_dump(o)
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
61
|
+
o.ordered_dumped!
|
62
|
+
pi = o.preferred_identifier
|
63
|
+
|
64
|
+
supers = o.supertypes
|
65
|
+
if (supers.size > 0)
|
66
|
+
# Ignore identification by a supertype:
|
67
|
+
pi = nil if pi && pi.role_sequence.all_role_ref.detect{|rr| rr.role.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance) }
|
68
|
+
subtype_dump(o, supers, pi)
|
69
|
+
else
|
70
|
+
non_subtype_dump(o, pi)
|
71
|
+
end
|
72
|
+
pi.ordered_dumped! if pi
|
73
73
|
end
|
74
74
|
|
75
75
|
def append_ring_to_reading(reading, ring)
|
@@ -193,9 +193,9 @@ module ActiveFacts
|
|
193
193
|
end
|
194
194
|
(entity_type.is_independent ? ' independent' : '') +
|
195
195
|
" identified by its #{value_residual}#{constraint_text}#{mapping_pragma(entity_type, true)}" +
|
196
|
-
|
197
|
-
|
198
|
-
|
196
|
+
entity_type.concept.all_context_note_as_relevant_concept.map do |cn|
|
197
|
+
cn.verbalise
|
198
|
+
end.join("\n") +
|
199
199
|
(fact_readings.size > 0 ? " where\n\t" : "") +
|
200
200
|
fact_readings*",\n\t"
|
201
201
|
end
|
@@ -230,9 +230,9 @@ module ActiveFacts
|
|
230
230
|
(entity_type.is_independent ? ' independent' : '') +
|
231
231
|
" identified by #{ irn*" and " }" +
|
232
232
|
mapping_pragma(entity_type, true) +
|
233
|
-
|
234
|
-
|
235
|
-
|
233
|
+
entity_type.concept.all_context_note_as_relevant_concept.map do |cn|
|
234
|
+
cn.verbalise
|
235
|
+
end.join("\n") +
|
236
236
|
" where\n\t"+identifying_fact_text
|
237
237
|
end
|
238
238
|
|
@@ -294,8 +294,8 @@ module ActiveFacts
|
|
294
294
|
# Alternate identification of objectified fact type?
|
295
295
|
primary_supertype = supertypes[0]
|
296
296
|
if fact_type.all_role.size > 1 and
|
297
|
-
|
298
|
-
|
297
|
+
pi = fact_type.entity_type.preferred_identifier and
|
298
|
+
primary_supertype && primary_supertype.preferred_identifier != pi
|
299
299
|
puts identified_by(o, pi) + ';'
|
300
300
|
return
|
301
301
|
end
|
@@ -369,7 +369,7 @@ module ActiveFacts
|
|
369
369
|
if role_proximity == :proximate
|
370
370
|
verbaliser.role_refs_have_subtype_steps(c.role_sequence)
|
371
371
|
else
|
372
|
-
|
372
|
+
roles = c.role_sequence.all_role_ref.map{|rr|rr.role}
|
373
373
|
join_over, joined_roles = ActiveFacts::Metamodel.plays_over(roles, role_proximity)
|
374
374
|
verbaliser.roles_have_same_player(joined_roles) if join_over
|
375
375
|
end
|
@@ -514,18 +514,18 @@ module ActiveFacts
|
|
514
514
|
end
|
515
515
|
|
516
516
|
def constraint_dump(c)
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
517
|
+
case c
|
518
|
+
when ActiveFacts::Metamodel::PresenceConstraint
|
519
|
+
dump_presence_constraint(c)
|
520
|
+
when ActiveFacts::Metamodel::RingConstraint
|
521
|
+
dump_ring_constraint(c)
|
522
|
+
when ActiveFacts::Metamodel::SetComparisonConstraint # includes SetExclusionConstraint, SetEqualityConstraint
|
523
|
+
dump_set_comparison_constraint(c)
|
524
|
+
when ActiveFacts::Metamodel::SubsetConstraint
|
525
|
+
dump_subset_constraint(c)
|
526
|
+
else
|
527
|
+
"#{c.class.basename} #{c.name}: unhandled constraint type"
|
528
|
+
end
|
529
529
|
end
|
530
530
|
|
531
531
|
# Find the common supertype of these object_types.
|
@@ -586,7 +586,7 @@ module ActiveFacts
|
|
586
586
|
end
|
587
587
|
|
588
588
|
expanded = verbaliser.expand_reading(reading, frequency_constraints, define_role_names, value_constraints)
|
589
|
-
|
589
|
+
expanded = "it is not the case that "+expanded if (reading.is_negative)
|
590
590
|
|
591
591
|
if (ft_rings = @ring_constraints_by_fact[reading.fact_type]) &&
|
592
592
|
(ring = ft_rings.detect{|rc| !rc.ordered_dumped})
|
@@ -608,29 +608,29 @@ module ActiveFacts
|
|
608
608
|
end
|
609
609
|
frequency_constraints = [] unless frequency_constraints.detect{|fc| fc[0] != "some" }
|
610
610
|
|
611
|
-
|
612
|
-
|
613
|
-
|
611
|
+
expanded = verbaliser.expand_reading(reading, frequency_constraints)
|
612
|
+
expanded = "it is not the case that "+expanded if (reading.is_negative)
|
613
|
+
expanded
|
614
614
|
end
|
615
615
|
|
616
616
|
def build_indices
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
633
|
-
|
617
|
+
@presence_constraints_by_fact = Hash.new{ |h, k| h[k] = [] }
|
618
|
+
@ring_constraints_by_fact = Hash.new{ |h, k| h[k] = [] }
|
619
|
+
|
620
|
+
@vocabulary.all_constraint.each { |c|
|
621
|
+
case c
|
622
|
+
when ActiveFacts::Metamodel::PresenceConstraint
|
623
|
+
fact_types = c.role_sequence.all_role_ref.map{|rr| rr.role.fact_type}.uniq # All fact types spanned by this constraint
|
624
|
+
if fact_types.size == 1 # There's only one, save it:
|
625
|
+
# trace "Single-fact constraint on #{fact_types[0].concept.guid}: #{c.name}"
|
626
|
+
(@presence_constraints_by_fact[fact_types[0]] ||= []) << c
|
627
|
+
end
|
628
|
+
when ActiveFacts::Metamodel::RingConstraint
|
629
|
+
(@ring_constraints_by_fact[c.role.fact_type] ||= []) << c
|
630
|
+
else
|
631
|
+
# trace "Found unhandled constraint #{c.class} #{c.name}"
|
632
|
+
end
|
633
|
+
}
|
634
634
|
end
|
635
635
|
|
636
636
|
end
|
@@ -655,12 +655,12 @@ module ActiveFacts
|
|
655
655
|
}#{
|
656
656
|
unit && " "+unit.name
|
657
657
|
}#{
|
658
|
-
|
658
|
+
transaction_phase && " auto-assigned at "+transaction_phase
|
659
|
+
}#{
|
660
|
+
concept.all_context_note_as_relevant_concept.map do |cn|
|
661
|
+
cn.verbalise
|
662
|
+
end.join("\n")
|
659
663
|
}#{
|
660
|
-
concept.all_context_note_as_relevant_concept.map do |cn|
|
661
|
-
cn.verbalise
|
662
|
-
end.join("\n")
|
663
|
-
}#{
|
664
664
|
value_constraint && " "+value_constraint.describe
|
665
665
|
};"
|
666
666
|
end
|
@@ -675,20 +675,20 @@ module ActiveFacts
|
|
675
675
|
|
676
676
|
if d = coefficient.denominator and d != 1
|
677
677
|
"/#{d}"
|
678
|
-
|
679
|
-
|
678
|
+
else
|
679
|
+
''
|
680
680
|
end +
|
681
681
|
|
682
682
|
' '
|
683
683
|
else
|
684
684
|
'1 '
|
685
685
|
end
|
686
|
-
|
687
|
-
|
686
|
+
else
|
687
|
+
''
|
688
688
|
end +
|
689
689
|
|
690
|
-
|
691
|
-
|
690
|
+
all_derivation_as_derived_unit.
|
691
|
+
sort_by{|d| d.base_unit.name}.
|
692
692
|
# REVISIT: Sort base units
|
693
693
|
# REVISIT: convert negative powers to division?
|
694
694
|
map do |der|
|
@@ -698,15 +698,15 @@ module ActiveFacts
|
|
698
698
|
|
699
699
|
if o = offset and o != 0
|
700
700
|
"+ #{o.to_s('F')} "
|
701
|
-
|
702
|
-
|
701
|
+
else
|
702
|
+
''
|
703
703
|
end +
|
704
704
|
|
705
705
|
"converts to #{name}#{plural_name ? '/'+plural_name : ''}" +
|
706
706
|
|
707
|
-
|
707
|
+
(coefficient && !coefficient.is_precise ? ' approximately' : '') +
|
708
708
|
|
709
|
-
|
709
|
+
(ephemera_url ? " ephemera #{ephemera_url}" : '') +
|
710
710
|
|
711
711
|
';'
|
712
712
|
end
|
@@ -16,322 +16,322 @@ module ActiveFacts
|
|
16
16
|
# afgen --diagrams/json <file>.cql=diagrams
|
17
17
|
class JSON
|
18
18
|
private
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
def initialize(vocabulary)
|
20
|
+
@vocabulary = vocabulary
|
21
|
+
@vocabulary = @vocabulary.Vocabulary.values[0] if ActiveFacts::API::Constellation === @vocabulary
|
22
|
+
end
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
def puts(*a)
|
25
|
+
@out.puts *a
|
26
|
+
end
|
27
27
|
|
28
28
|
public
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
29
|
+
def generate(out = $>)
|
30
|
+
@out = out
|
31
|
+
uuids = {}
|
32
|
+
|
33
|
+
puts "{ model: '#{@vocabulary.name}',\n" +
|
34
|
+
"diagrams: [\n#{
|
35
|
+
@vocabulary.all_diagram.sort_by{|o| o.name.gsub(/ /,'')}.map do |d|
|
36
|
+
j = {:uuid => (uuids[d] ||= uuid_from_id(d)), :name => d.name}
|
37
|
+
" #{j.to_json}"
|
38
|
+
end*",\n"
|
39
|
+
}\n ],"
|
40
|
+
|
41
|
+
object_types = @vocabulary.all_object_type.sort_by{|o| o.name.gsub(/ /,'')}
|
42
|
+
puts " object_types: [\n#{
|
43
|
+
object_types.sort_by{|o|o.identifying_role_values.inspect}.map do |o|
|
44
|
+
uuids[o] ||= uuid_from_id(o)
|
45
|
+
ref_mode = nil
|
46
|
+
if o.is_a?(ActiveFacts::Metamodel::EntityType) and
|
47
|
+
p = o.preferred_identifier and
|
48
|
+
(rrs = p.role_sequence.all_role_ref).size == 1 and
|
49
|
+
!(o.fact_type && o.fact_type.all_role.size == 1) and
|
50
|
+
(r = rrs.single.role).fact_type != o.fact_type and
|
51
|
+
r.object_type.is_a?(ActiveFacts::Metamodel::ValueType) and
|
52
|
+
!r.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
|
53
|
+
ref_mode = "#{r.object_type.name}"
|
54
|
+
ref_mode.sub!(%r{#{o.name} *}, '.')
|
55
|
+
end
|
56
|
+
j = {
|
57
|
+
:uuid => uuids[o],
|
58
|
+
:name => o.name,
|
59
|
+
:shapes => o.all_object_type_shape.sort_by{|s| [s.location.x, s.location.y]}.map do |shape|
|
60
|
+
x = { :diagram => uuids[shape.orm_diagram],
|
61
|
+
:is_expanded => shape.is_expanded,
|
62
|
+
:uuid => uuid_from_id(shape),
|
63
|
+
:x => shape.location.x,
|
64
|
+
:y => shape.location.y
|
65
|
+
}
|
66
|
+
x[:is_expanded] = true if ref_mode && shape.is_expanded # Don't show the reference mode
|
67
|
+
x
|
68
|
+
end
|
69
|
+
}
|
70
|
+
j[:ref_mode] = ref_mode if ref_mode
|
71
|
+
j[:independent] = true if o.is_independent
|
72
|
+
|
73
|
+
if o.is_a?(ActiveFacts::Metamodel::EntityType)
|
74
|
+
# Entity Type may be objectified, and may have supertypes:
|
75
|
+
if o.fact_type
|
76
|
+
uuid = (uuids[o.fact_type] ||= uuid_from_id(o.fact_type))
|
77
|
+
j[:objectifies] = uuid
|
78
|
+
j[:implicit] = true if o.concept.implication_rule
|
79
|
+
end
|
80
|
+
if o.all_type_inheritance_as_subtype.size > 0
|
81
|
+
j[:supertypes] = o.
|
82
|
+
all_type_inheritance_as_subtype.
|
83
|
+
sort_by{|ti| ti.provides_identification ? 0 : 1}.
|
84
|
+
map{|ti|
|
85
|
+
[ uuids[ti.supertype] ||= uuid_from_id(ti.supertype),
|
86
|
+
uuids[ti.supertype_role] = uuid_from_id(ti.supertype_role)
|
87
|
+
]
|
88
|
+
}
|
89
|
+
end
|
90
|
+
else
|
91
|
+
# ValueType usually has a supertype:
|
92
|
+
if (o.supertype)
|
93
|
+
j[:supertype] = (uuids[o.supertype] ||= uuid_from_id(o.supertype))
|
94
|
+
end
|
95
|
+
end
|
96
|
+
# REVISIT: Place a ValueConstraint and shape
|
97
|
+
" #{j.to_json}"
|
98
|
+
end*",\n"
|
99
|
+
}\n ],"
|
100
|
+
|
101
|
+
fact_types = @vocabulary.constellation.
|
102
|
+
FactType.values.
|
103
|
+
reject{|ft|
|
104
|
+
ActiveFacts::Metamodel::LinkFactType === ft || ActiveFacts::Metamodel::TypeInheritance === ft
|
105
|
+
}
|
106
|
+
puts " fact_types: [\n#{
|
107
|
+
fact_types.sort_by{|f| f.identifying_role_values.inspect}.map do |f|
|
108
|
+
uuids[f] ||= uuid_from_id(f)
|
109
|
+
j = {:uuid => uuids[f]}
|
110
|
+
|
111
|
+
if f.entity_type
|
112
|
+
j[:objectified_as] = uuids[f.entity_type]
|
113
|
+
end
|
114
|
+
|
115
|
+
# Emit roles
|
116
|
+
roles = f.all_role.sort_by{|r| r.ordinal }
|
117
|
+
j[:roles] = roles.map do |role|
|
118
|
+
uuid = (uuids[role] ||= uuid_from_id(role))
|
119
|
+
# REVISIT: Internal Mandatory Constraints
|
120
|
+
# REVISIT: Place a ValueConstraint and shape
|
121
|
+
# REVISIT: Place a RoleName shape
|
122
|
+
{:uuid => uuid, :player => uuids[role.object_type]}
|
123
|
+
# N.B. The object_type shape to which this role is attached is not in the meta-model
|
124
|
+
# Attach to the closest instance on this diagram (if any)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Emit readings. Each is a [role_order, text] pair
|
128
|
+
j[:readings] = f.all_reading.map do |r|
|
129
|
+
role_refs = r.role_sequence.all_role_ref_in_order
|
130
|
+
[
|
131
|
+
role_order(uuids, role_refs.map{|rr| rr.role}, roles),
|
132
|
+
r.text.gsub(/\{([0-9])\}/) do |insert|
|
133
|
+
role_ref = role_refs[$1.to_i]
|
134
|
+
la = role_ref.leading_adjective
|
135
|
+
la = nil if la == ''
|
136
|
+
ta = role_ref.trailing_adjective
|
137
|
+
ta = nil if ta == ''
|
138
|
+
(la ? la+'-' : '') +
|
139
|
+
(la && la.index(' ') ? ' ' : '') +
|
140
|
+
insert +
|
141
|
+
(ta && ta.index(' ') ? ' ' : '') +
|
142
|
+
(ta ? '-'+ta : '')
|
143
|
+
end
|
144
|
+
]
|
145
|
+
end.sort_by{|(ro,text)| ro }.map do |(ro,text)|
|
146
|
+
[ ro, text ]
|
147
|
+
end
|
148
|
+
|
149
|
+
# Emit shapes
|
150
|
+
j[:shapes] = f.all_fact_type_shape.sort_by{|s| [s.location.x, s.location.y]}.map do |shape|
|
151
|
+
sj = {
|
152
|
+
:diagram => uuids[shape.orm_diagram],
|
153
|
+
:uuid => uuid_from_id(shape),
|
154
|
+
:x => shape.location.x,
|
155
|
+
:y => shape.location.y
|
156
|
+
}
|
157
|
+
|
158
|
+
# Add the role_order, if specified
|
159
|
+
if shape.all_role_display.size > 0
|
160
|
+
if shape.all_role_display.size != roles.size
|
161
|
+
raise "Invalid RoleDisplay for #{f.default_reading} in #{shape.orm_diagram.name} diagram"
|
162
|
+
end
|
163
|
+
ro = role_order(
|
164
|
+
uuids,
|
165
|
+
shape.all_role_display.sort_by{|rd| rd.ordinal }.map{|rd| rd.role },
|
166
|
+
roles
|
167
|
+
)
|
168
|
+
sj[:role_order] = ro if ro
|
169
|
+
end
|
170
|
+
|
171
|
+
# REVISIT: Place the ReadingShape
|
172
|
+
|
173
|
+
# Emit the location of the name, if objectified
|
174
|
+
if n = shape.objectified_fact_type_name_shape
|
175
|
+
sj[:name_shape] = {:x => n.location.x, :y => n.location.y}
|
176
|
+
end
|
177
|
+
sj
|
178
|
+
end
|
179
|
+
|
180
|
+
# Emit Internal Presence Constraints
|
181
|
+
f.internal_presence_constraints.to_a.sort_by{|ipc, z|
|
182
|
+
[ipc.is_preferred_identifier ? 0 : 1, ipc.is_mandatory ? 0 : 1, ipc.min_frequency || 0, ipc.max_frequency || 1_000]
|
183
|
+
}.each do |ipc|
|
184
|
+
uuid = (uuids[ipc] ||= uuid_from_id(ipc))
|
185
|
+
|
186
|
+
constraint = {
|
187
|
+
:uuid => uuid,
|
188
|
+
:min => ipc.min_frequency,
|
189
|
+
:max => ipc.max_frequency,
|
190
|
+
:is_preferred => ipc.is_preferred_identifier,
|
191
|
+
:mandatory => ipc.is_mandatory
|
192
|
+
}
|
193
|
+
|
194
|
+
# Get the role (or excluded role, for a UC)
|
195
|
+
roles = ipc.role_sequence.all_role_ref_in_order.map{|r| r.role}
|
196
|
+
if roles.size > 1 || (!ipc.is_mandatory && ipc.max_frequency == 1)
|
197
|
+
# This can be only a uniqueness constraint. Record the missing role, if any
|
198
|
+
role = (f.all_role.to_a - roles)[0]
|
199
|
+
constraint[:uniqueExcept] = uuids[role]
|
200
|
+
else
|
201
|
+
# An internal mandatory or frequency constraint applies to only one role.
|
202
|
+
# If it's also unique (max == 1), that applies on the counterpart role.
|
203
|
+
# You can also have a mandatory frequency constraint, but that applies on this role.
|
204
|
+
constraint[:role] = uuids[roles[0]]
|
205
|
+
end
|
206
|
+
(j[:constraints] ||= []) << constraint
|
207
|
+
end
|
208
|
+
|
209
|
+
# Add ring constraints
|
210
|
+
f.all_role_in_order.
|
211
|
+
map{|r| r.all_ring_constraint.to_a+r.all_ring_constraint_as_other_role.to_a }.
|
212
|
+
flatten.uniq.each do |ring|
|
213
|
+
(j[:constraints] ||= []) << {
|
214
|
+
:uuid => (uuids[ring] ||= uuid_from_id(ring)),
|
215
|
+
:shapes => ring.all_constraint_shape.sort_by{|s| [s.location.x, s.location.y]}.map do |shape|
|
216
|
+
{ :diagram => uuids[shape.orm_diagram],
|
217
|
+
:uuid => uuid_from_id(shape),
|
218
|
+
:x => shape.location.x,
|
219
|
+
:y => shape.location.y
|
220
|
+
}
|
221
|
+
end,
|
222
|
+
:ringKind => ring.ring_type,
|
223
|
+
:roles => [uuids[ring.role], uuids[ring.other_role]]
|
224
|
+
# REVISIT: Deontic, enforcement
|
225
|
+
}
|
226
|
+
end
|
227
|
+
|
228
|
+
# REVISIT: RotationSetting
|
229
|
+
|
230
|
+
" #{j.to_json}"
|
231
|
+
end*",\n"
|
232
|
+
}\n ],"
|
233
|
+
|
234
|
+
constraints = @vocabulary.constellation.
|
235
|
+
Constraint.values
|
236
|
+
puts " constraints: [\n#{
|
237
|
+
constraints.sort_by{|c|c.identifying_role_values.inspect}.select{|c| !uuids[c]}.map do |c|
|
238
|
+
uuid = uuids[c] ||= uuid_from_id(c)
|
239
|
+
j = {
|
240
|
+
:uuid => uuid,
|
241
|
+
:type => c.class.basename,
|
242
|
+
:shapes => c.all_constraint_shape.sort_by{|s| [s.location.x, s.location.y]}.map do |shape|
|
243
|
+
{ :diagram => uuids[shape.orm_diagram],
|
244
|
+
:uuid => uuid_from_id(shape),
|
245
|
+
:x => shape.location.x,
|
246
|
+
:y => shape.location.y
|
247
|
+
}
|
248
|
+
end
|
249
|
+
}
|
250
|
+
|
251
|
+
if (c.enforcement)
|
252
|
+
# REVISIT: Deontic constraint
|
253
|
+
end
|
254
|
+
if (c.concept.all_context_note_as_relevant_concept.size > 0)
|
255
|
+
# REVISIT: Context Notes
|
256
|
+
end
|
257
|
+
|
258
|
+
case c
|
259
|
+
when ActiveFacts::Metamodel::PresenceConstraint
|
260
|
+
j[:min_frequency] = c.min_frequency
|
261
|
+
j[:max_frequency] = c.max_frequency
|
262
|
+
j[:is_mandatory] = c.is_mandatory
|
263
|
+
j[:is_preferred_identifier] = c.is_preferred_identifier
|
264
|
+
rss = [c.role_sequence.all_role_ref_in_order.map(&:role)]
|
265
|
+
|
266
|
+
# Ignore internal presence constraints on TypeInheritance fact types
|
267
|
+
next nil if !c.role_sequence.all_role_ref.
|
268
|
+
detect{|rr|
|
269
|
+
!rr.role.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
|
270
|
+
}
|
271
|
+
|
272
|
+
when ActiveFacts::Metamodel::RingConstraint
|
273
|
+
next nil # These are emitted with the corresponding fact type
|
274
|
+
|
275
|
+
when ActiveFacts::Metamodel::SetComparisonConstraint
|
276
|
+
rss = c.
|
277
|
+
all_set_comparison_roles.sort_by{|scr| scr.ordinal}.
|
278
|
+
map{|scr| scr.role_sequence.all_role_ref_in_order.map(&:role) }
|
279
|
+
if (ActiveFacts::Metamodel::SetExclusionConstraint === c)
|
280
|
+
j[:is_mandatory] = c.is_mandatory
|
281
|
+
end
|
282
|
+
|
283
|
+
when ActiveFacts::Metamodel::SubsetConstraint
|
284
|
+
rss = [c.subset_role_sequence, c.superset_role_sequence].
|
285
|
+
map{|rs| rs.all_role_ref_in_order.map(&:role) }
|
286
|
+
|
287
|
+
when ActiveFacts::Metamodel::ValueConstraint
|
288
|
+
next nil # REVISIT: Should have been handled elsewhere
|
289
|
+
if (c.role)
|
290
|
+
# Should have been handled as role.role_value_constraint
|
291
|
+
elsif (c.value_type)
|
292
|
+
# Should have been handled as object_type.value_constraint
|
293
|
+
end
|
294
|
+
j[:allowed_ranges] = c.all_allowed_range.map{|ar|
|
295
|
+
[ ar.value_range.minimum_bound, ar.value_range.maximum_bound ].
|
296
|
+
map{|b| [b.value.literal, b.value.unit.name, b.is_inclusive] }
|
297
|
+
}
|
298
|
+
|
299
|
+
else
|
300
|
+
raise "REVISIT: Constraint type not yet dumped to JSON"
|
301
|
+
end
|
302
|
+
|
303
|
+
# rss contains the constrained role sequences; map to uuids
|
304
|
+
j[:role_sequences] = rss.map{|rs|
|
305
|
+
rs.map do |role|
|
306
|
+
uuids[role]
|
307
|
+
end
|
308
|
+
}
|
309
|
+
|
310
|
+
" #{j.to_json}"
|
311
|
+
end.compact*",\n"
|
312
|
+
}\n ]"
|
313
|
+
|
314
|
+
puts "}"
|
315
|
+
end
|
316
|
+
|
317
|
+
def role_order(uuids, roles, order)
|
318
|
+
if (roles.size > 9)
|
319
|
+
roles.map{|r| uuids[r] }
|
320
|
+
else
|
321
|
+
roles.map{|r| order.index(r).to_s }*''
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
def uuid_from_id o
|
326
|
+
irvs = o.identifying_role_values.inspect
|
327
|
+
d = Digest::SHA1.digest irvs
|
328
|
+
# $stderr.puts "#{o.class.basename}: #{irvs}"
|
329
|
+
d[0,4].unpack("H8")[0]+'-'+
|
330
|
+
d[4,2].unpack("H4")[0]+'-'+
|
331
|
+
d[6,2].unpack("H4")[0]+'-'+
|
332
|
+
d[8,2].unpack("H4")[0]+'-'+
|
333
|
+
d[10,6].unpack("H6")[0]
|
334
|
+
end
|
335
335
|
|
336
336
|
end
|
337
337
|
end
|