activefacts 1.5.0 → 1.5.1
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/examples/CQL/Metamodel.cql +37 -40
- data/lib/activefacts/cql/ObjectTypes.treetop +14 -4
- data/lib/activefacts/cql/compiler/entity_type.rb +7 -2
- data/lib/activefacts/cql/compiler/fact_type.rb +3 -3
- data/lib/activefacts/cql/compiler/value_type.rb +4 -1
- data/lib/activefacts/generate/sql/server.rb +2 -1
- data/lib/activefacts/generate/transform/surrogate.rb +156 -156
- data/lib/activefacts/persistence/tables.rb +1 -1
- data/lib/activefacts/version.rb +1 -1
- data/lib/activefacts/vocabulary/extensions.rb +262 -261
- data/lib/activefacts/vocabulary/metamodel.rb +16 -15
- metadata +2 -2
@@ -73,7 +73,7 @@ module ActiveFacts
|
|
73
73
|
@tentative = false
|
74
74
|
|
75
75
|
# Always a table if marked so
|
76
|
-
if is_independent
|
76
|
+
if is_independent or concept.all_mapping_annotation.include?('separate')
|
77
77
|
trace :absorption, "EntityType #{name} is declared independent"
|
78
78
|
return @is_table = true
|
79
79
|
end
|
data/lib/activefacts/version.rb
CHANGED
@@ -68,94 +68,94 @@ module ActiveFacts
|
|
68
68
|
|
69
69
|
class Concept
|
70
70
|
def describe
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
71
|
+
case
|
72
|
+
when object_type; "#{object_type.class.basename} #{object_type.name.inspect}"
|
73
|
+
when fact_type; "FactType #{fact_type.default_reading.inspect}"
|
74
|
+
when role; "Role in #{role.fact_type.describe(role)}"
|
75
|
+
when constraint; constraint.describe
|
76
|
+
when instance; "Instance #{instance.verbalise}"
|
77
|
+
when fact; "Fact #{fact.verbalise}"
|
78
|
+
when query; query.describe
|
79
|
+
when context_note; "ContextNote#{context_note.verbalise}"
|
80
|
+
when unit; "Unit #{unit.describe}"
|
81
|
+
when population; "Population: #{population.name}"
|
82
|
+
else
|
83
|
+
raise "ROGUE CONCEPT OF NO TYPE"
|
84
|
+
end
|
85
85
|
end
|
86
86
|
|
87
87
|
def embodied_as
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
88
|
+
case
|
89
|
+
when object_type; object_type
|
90
|
+
when fact_type; fact_type
|
91
|
+
when role; role
|
92
|
+
when constraint; constraint
|
93
|
+
when instance; instance
|
94
|
+
when fact; fact
|
95
|
+
when query; query
|
96
|
+
when context_note; context_note
|
97
|
+
when unit; unit
|
98
|
+
when population; population
|
99
|
+
else
|
100
|
+
raise "ROGUE CONCEPT OF NO TYPE"
|
101
|
+
end
|
102
102
|
end
|
103
103
|
|
104
104
|
# Return an array of all Concepts that must be defined before this concept can be defined:
|
105
105
|
def precursors
|
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
|
-
|
106
|
+
case body = embodied_as
|
107
|
+
when ActiveFacts::Metamodel::ValueType
|
108
|
+
[ body.supertype, body.unit ] +
|
109
|
+
body.all_facet.map{|f| f.facet_value_type } +
|
110
|
+
body.all_facet_restriction.map{|vr| vr.value.unit}
|
111
|
+
when ActiveFacts::Metamodel::EntityType
|
112
|
+
# You can't define the preferred_identifier fact types until you define the entity type,
|
113
|
+
# but the objects which play the identifying roles must be defined:
|
114
|
+
body.preferred_identifier.role_sequence.all_role_ref.map {|rr| rr.role.object_type } +
|
115
|
+
# You can't define the objectified fact type until you define the entity type:
|
116
|
+
# [ body.fact_type ] # If it's an objectification
|
117
|
+
body.all_type_inheritance_as_subtype.map{|ti| ti.supertype} # If it's a subtype
|
118
|
+
when FactType
|
119
|
+
body.all_role.map(&:object_type)
|
120
|
+
when Role # We don't consider roles as they cannot be separately defined
|
121
|
+
[]
|
122
|
+
when ActiveFacts::Metamodel::PresenceConstraint
|
123
|
+
body.role_sequence.all_role_ref.map do |rr|
|
124
|
+
rr.role.fact_type
|
125
|
+
end
|
126
|
+
when ActiveFacts::Metamodel::ValueConstraint
|
127
|
+
[ body.role ? body.role.fact_type : nil, body.value_type ] +
|
128
|
+
body.all_allowed_range.map do |ar|
|
129
|
+
[ ar.value_range.minimum_bound, ar.value_range.maximum_bound ].compact.map{|b| b.value.unit}
|
130
|
+
end
|
131
|
+
when ActiveFacts::Metamodel::SubsetConstraint
|
132
|
+
body.subset_role_sequence.all_role_ref.map{|rr| rr.role.fact_type } +
|
133
|
+
body.superset_role_sequence.all_role_ref.map{|rr| rr.role.fact_type }
|
134
|
+
when ActiveFacts::Metamodel::SetComparisonConstraint
|
135
|
+
body.all_set_comparison_roles.map{|scr| scr.role_sequence.all_role_ref.map{|rr| rr.role.fact_type } }
|
136
|
+
when ActiveFacts::Metamodel::RingConstraint
|
137
|
+
[ body.role.fact_type, body.other_role.fact_type ]
|
138
|
+
when Instance
|
139
|
+
[ body.population, body.object_type, body.value ? body.value.unit : nil ]
|
140
|
+
when Fact
|
141
|
+
[ body.population, body.fact_type ]
|
142
|
+
when Query
|
143
|
+
body.all_variable.map do |v|
|
144
|
+
[ v.object_type,
|
145
|
+
v.value ? v.value.unit : nil,
|
146
|
+
v.step ? v.step.fact_type : nil
|
147
|
+
] +
|
148
|
+
v.all_play.map{|p| p.role.fact_type }
|
149
|
+
end
|
150
|
+
when ContextNote
|
151
|
+
[]
|
152
|
+
when Unit
|
153
|
+
body.all_derivation_as_derived_unit.map{|d| d.base_unit }
|
154
|
+
when Population
|
155
|
+
[]
|
156
|
+
else
|
157
|
+
raise "ROGUE CONCEPT OF NO TYPE"
|
158
|
+
end.flatten.compact.uniq.map{|c| c.concept }
|
159
159
|
end
|
160
160
|
end
|
161
161
|
|
@@ -168,23 +168,23 @@ module ActiveFacts
|
|
168
168
|
|
169
169
|
class Unit
|
170
170
|
def describe
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
171
|
+
'Unit' +
|
172
|
+
name +
|
173
|
+
(plural_name ? '/'+plural_name : '') +
|
174
|
+
'=' +
|
175
|
+
coefficient.to_s+'*' +
|
176
|
+
all_derivation_as_derived_unit.map do |derivation|
|
177
|
+
derivation.base_unit.name +
|
178
|
+
(derivation.exponent != 1 ? derivation.exponent.to_s : '')
|
179
|
+
end.join('') +
|
180
|
+
(offset ? ' + '+offset.to_s : '')
|
181
181
|
end
|
182
182
|
end
|
183
183
|
|
184
184
|
class Coefficient
|
185
185
|
def to_s
|
186
|
-
|
187
|
-
|
186
|
+
numerator.to_s +
|
187
|
+
(denominator != 1 ? '/' + denominator.to_s : '')
|
188
188
|
end
|
189
189
|
end
|
190
190
|
|
@@ -212,14 +212,14 @@ module ActiveFacts
|
|
212
212
|
|
213
213
|
# Does any role of this fact type participate in a preferred identifier?
|
214
214
|
def is_existential
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
215
|
+
return false if all_role.size > 2
|
216
|
+
all_role.detect do |role|
|
217
|
+
role.all_role_ref.detect do |rr|
|
218
|
+
rr.role_sequence.all_presence_constraint.detect do |pc|
|
219
|
+
pc.is_preferred_identifier
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
223
|
end
|
224
224
|
|
225
225
|
def internal_presence_constraints
|
@@ -244,7 +244,7 @@ module ActiveFacts
|
|
244
244
|
# NORMA doesn't create an implicit fact type here, rather the fact type has an implicit extra role, so looks like a binary
|
245
245
|
# We only do it when the unary fact type is not objectified
|
246
246
|
link_fact_type = @constellation.LinkFactType(:new, :implying_role => role)
|
247
|
-
|
247
|
+
link_fact_type.concept.implication_rule = 'unary'
|
248
248
|
entity_type = @entity_type || implicit_boolean_type(role.object_type.vocabulary)
|
249
249
|
phantom_role = @constellation.Role(link_fact_type, 0, :object_type => entity_type, :concept => :new)
|
250
250
|
end
|
@@ -262,13 +262,13 @@ module ActiveFacts
|
|
262
262
|
end
|
263
263
|
|
264
264
|
def compatible_readings types_array
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
265
|
+
all_reading.select do |reading|
|
266
|
+
ok = true
|
267
|
+
reading.role_sequence.all_role_ref_in_order.each_with_index do |rr, i|
|
268
|
+
ok = false unless types_array[i].include?(rr.role.object_type)
|
269
|
+
end
|
270
|
+
ok
|
271
|
+
end
|
272
272
|
end
|
273
273
|
end
|
274
274
|
|
@@ -289,7 +289,7 @@ module ActiveFacts
|
|
289
289
|
end
|
290
290
|
|
291
291
|
def is_mandatory
|
292
|
-
|
292
|
+
return fact_type.implying_role.is_mandatory if fact_type.is_a?(LinkFactType)
|
293
293
|
all_role_ref.detect{|rr|
|
294
294
|
rs = rr.role_sequence
|
295
295
|
rs.all_role_ref.size == 1 and
|
@@ -308,20 +308,20 @@ module ActiveFacts
|
|
308
308
|
def is_functional
|
309
309
|
fact_type.entity_type or
|
310
310
|
fact_type.all_role.size != 2 or
|
311
|
-
|
311
|
+
is_unique
|
312
312
|
end
|
313
313
|
|
314
314
|
def is_unique
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
315
|
+
all_role_ref.detect do |rr|
|
316
|
+
rr.role_sequence.all_role_ref.size == 1 and
|
317
|
+
rr.role_sequence.all_presence_constraint.detect do |pc|
|
318
|
+
pc.max_frequency == 1 and !pc.enforcement # Alethic uniqueness constraint
|
319
|
+
end
|
320
|
+
end
|
321
321
|
end
|
322
322
|
|
323
323
|
def name
|
324
|
-
|
324
|
+
role_name || object_type.name
|
325
325
|
end
|
326
326
|
|
327
327
|
end
|
@@ -336,7 +336,7 @@ module ActiveFacts
|
|
336
336
|
end
|
337
337
|
|
338
338
|
def role_name(separator = "-")
|
339
|
-
|
339
|
+
return 'UNKNOWN' unless role
|
340
340
|
name_array =
|
341
341
|
if role.fact_type.all_role.size == 1
|
342
342
|
if role.fact_type.is_a?(LinkFactType)
|
@@ -427,10 +427,10 @@ module ActiveFacts
|
|
427
427
|
end
|
428
428
|
|
429
429
|
def common_supertype(other)
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
430
|
+
return nil unless other.is_?(ActiveFacts::Metamodel::ValueType)
|
431
|
+
return self if other.supertypes_transitive.include?(self)
|
432
|
+
return other if supertypes_transitive.include(other)
|
433
|
+
nil
|
434
434
|
end
|
435
435
|
end
|
436
436
|
|
@@ -573,14 +573,14 @@ module ActiveFacts
|
|
573
573
|
#pi = supertype.preferred_identifier
|
574
574
|
#return nil
|
575
575
|
elsif fact_type
|
576
|
-
|
576
|
+
possible_pi = nil
|
577
577
|
fact_type.all_role.each{|role|
|
578
578
|
role.all_role_ref.each{|role_ref|
|
579
579
|
# Discount role sequences that contain roles not in this fact type:
|
580
580
|
next if role_ref.role_sequence.all_role_ref.detect{|rr| rr.role.fact_type != fact_type }
|
581
581
|
role_ref.role_sequence.all_presence_constraint.each{|pc|
|
582
|
-
|
583
|
-
|
582
|
+
next unless pc.max_frequency == 1
|
583
|
+
possible_pi = pc
|
584
584
|
next unless pc.is_preferred_identifier
|
585
585
|
pi = pc
|
586
586
|
break
|
@@ -589,11 +589,12 @@ module ActiveFacts
|
|
589
589
|
}
|
590
590
|
break if pi
|
591
591
|
}
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
592
|
+
if !pi && possible_pi
|
593
|
+
trace :pi, "Using existing PC as PI for #{name}"
|
594
|
+
pi = possible_pi
|
595
|
+
end
|
596
596
|
else
|
597
|
+
byebug
|
597
598
|
trace :pi, "No PI found for #{name}"
|
598
599
|
end
|
599
600
|
end
|
@@ -646,10 +647,10 @@ module ActiveFacts
|
|
646
647
|
end
|
647
648
|
|
648
649
|
def common_supertype(other)
|
649
|
-
|
650
|
-
|
651
|
-
|
652
|
-
|
650
|
+
return nil unless other.is_?(ActiveFacts::Metamodel::EntityType)
|
651
|
+
candidates = supertypes_transitive & other.supertypes_transitive
|
652
|
+
return candidates[0] if candidates.size <= 1
|
653
|
+
candidates[0] # REVISIT: This might not be the closest supertype
|
653
654
|
end
|
654
655
|
|
655
656
|
# This entity type has just objectified a fact type. Create the necessary ImplicitFactTypes with phantom roles
|
@@ -657,11 +658,11 @@ module ActiveFacts
|
|
657
658
|
fact_type.all_role.map do |role|
|
658
659
|
next if role.link_fact_type # Already exists
|
659
660
|
link_fact_type = @constellation.LinkFactType(:new, :implying_role => role)
|
660
|
-
|
661
|
+
link_fact_type.concept.implication_rule = 'objectification'
|
661
662
|
phantom_role = @constellation.Role(link_fact_type, 0, :object_type => self, :concept => :new)
|
662
663
|
# We could create a copy of the visible external role here, but there's no need yet...
|
663
664
|
# Nor is there a need for a presence constraint, readings, etc.
|
664
|
-
|
665
|
+
link_fact_type
|
665
666
|
end
|
666
667
|
end
|
667
668
|
end
|
@@ -690,27 +691,27 @@ module ActiveFacts
|
|
690
691
|
|
691
692
|
expanded.gsub!(/\{#{i}\}/) do
|
692
693
|
role_ref = role_refs[i]
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
|
694
|
+
if role_ref.role
|
695
|
+
player = role_ref.role.object_type
|
696
|
+
role_name = role.role_name
|
697
|
+
role_name = nil if role_name == ""
|
698
|
+
if role_name && define_role_names == false
|
699
|
+
l_adj = t_adj = nil # When using role names, don't add adjectives
|
700
|
+
end
|
701
|
+
|
702
|
+
freq_con = frequency_constraints[i]
|
703
|
+
freq_con = freq_con.frequency if freq_con && freq_con.is_a?(ActiveFacts::Metamodel::PresenceConstraint)
|
704
|
+
if freq_con.is_a?(Array)
|
705
|
+
freq_con, player_name = *freq_con
|
706
|
+
else
|
707
|
+
player_name = player.name
|
708
|
+
end
|
709
|
+
else
|
710
|
+
# We have an unknown role. The reading cannot be correctly expanded
|
711
|
+
player_name = "UNKNOWN"
|
712
|
+
role_name = nil
|
713
|
+
freq_con = nil
|
714
|
+
end
|
714
715
|
|
715
716
|
literal = literals[i]
|
716
717
|
words = [
|
@@ -780,17 +781,17 @@ module ActiveFacts
|
|
780
781
|
|
781
782
|
class ValueConstraint
|
782
783
|
def describe
|
783
|
-
|
784
|
+
as_cql
|
784
785
|
end
|
785
786
|
|
786
787
|
def as_cql
|
787
788
|
"restricted to "+
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
789
|
+
( if regular_expression
|
790
|
+
'/' + regular_expression + '/'
|
791
|
+
else
|
792
|
+
'{' + all_allowed_range_sorted.map{|ar| ar.to_s(false) }*', ' + '}'
|
793
|
+
end
|
794
|
+
)
|
794
795
|
end
|
795
796
|
|
796
797
|
def all_allowed_range_sorted
|
@@ -883,32 +884,32 @@ module ActiveFacts
|
|
883
884
|
|
884
885
|
class SubsetConstraint
|
885
886
|
def describe
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
887
|
+
'SubsetConstraint(' +
|
888
|
+
subset_role_sequence.describe
|
889
|
+
' < ' +
|
890
|
+
superset_role_sequence.describe +
|
891
|
+
')'
|
891
892
|
end
|
892
893
|
end
|
893
894
|
|
894
895
|
class SetComparisonConstraint
|
895
896
|
def describe
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
897
|
+
self.class.basename+'(' +
|
898
|
+
all_set_comparison_roles.map do |scr|
|
899
|
+
scr.role_sequence.describe
|
900
|
+
end*',' +
|
901
|
+
')'
|
901
902
|
end
|
902
903
|
end
|
903
904
|
|
904
905
|
class RingConstraint
|
905
906
|
def describe
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
907
|
+
'RingConstraint(' +
|
908
|
+
ring_type.to_s+': ' +
|
909
|
+
role.describe+', ' +
|
910
|
+
other_role.describe+' in ' +
|
911
|
+
role.fact_type.default_reading +
|
912
|
+
')'
|
912
913
|
end
|
913
914
|
end
|
914
915
|
|
@@ -938,11 +939,11 @@ module ActiveFacts
|
|
938
939
|
end
|
939
940
|
|
940
941
|
def input_play
|
941
|
-
|
942
|
+
all_play.detect{|p| p.is_input}
|
942
943
|
end
|
943
944
|
|
944
945
|
def output_plays
|
945
|
-
|
946
|
+
all_play.reject{|p| p.is_input}
|
946
947
|
end
|
947
948
|
|
948
949
|
def is_unary_step
|
@@ -982,16 +983,16 @@ module ActiveFacts
|
|
982
983
|
class Query
|
983
984
|
def describe
|
984
985
|
steps_shown = {}
|
985
|
-
|
986
|
+
'Query(' +
|
986
987
|
all_variable.sort_by{|var| var.ordinal}.map do |variable|
|
987
|
-
|
988
|
-
|
989
|
-
|
990
|
-
|
991
|
-
|
992
|
-
|
993
|
-
|
994
|
-
|
988
|
+
variable.describe + ': ' +
|
989
|
+
variable.all_step.map do |step|
|
990
|
+
next if steps_shown[step]
|
991
|
+
steps_shown[step] = true
|
992
|
+
step.describe
|
993
|
+
end.compact.join(',')
|
994
|
+
end.join('; ') +
|
995
|
+
')'
|
995
996
|
end
|
996
997
|
|
997
998
|
def show
|
@@ -1062,18 +1063,18 @@ module ActiveFacts
|
|
1062
1063
|
end
|
1063
1064
|
|
1064
1065
|
def add_reading implicit_reading
|
1065
|
-
|
1066
|
-
|
1066
|
+
@readings ||= []
|
1067
|
+
@readings << implicit_reading
|
1067
1068
|
end
|
1068
1069
|
|
1069
1070
|
def all_reading
|
1070
1071
|
@readings ||=
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1072
|
+
[ ImplicitReading.new(
|
1073
|
+
self,
|
1074
|
+
implying_role.fact_type.entity_type ? "{0} involves {1}" : implying_role.fact_type.default_reading+" Boolean"
|
1075
|
+
)
|
1076
|
+
] +
|
1077
|
+
Array(implying_role.fact_type.entity_type ? ImplicitReading.new(self, "{1} is involved in {0}") : nil)
|
1077
1078
|
end
|
1078
1079
|
|
1079
1080
|
def reading_preferably_starting_with_role role, negated = false
|
@@ -1083,7 +1084,7 @@ module ActiveFacts
|
|
1083
1084
|
# This is only used for debugging, from RoleRef#describe
|
1084
1085
|
class ImplicitReading
|
1085
1086
|
attr_accessor :fact_type, :text
|
1086
|
-
|
1087
|
+
attr_reader :is_negative # Never true
|
1087
1088
|
|
1088
1089
|
def initialize(fact_type, text)
|
1089
1090
|
@fact_type = fact_type
|
@@ -1115,8 +1116,8 @@ module ActiveFacts
|
|
1115
1116
|
@role_refs
|
1116
1117
|
end
|
1117
1118
|
def all_role_ref_in_order
|
1118
|
-
|
1119
|
-
|
1119
|
+
@role_refs
|
1120
|
+
end
|
1120
1121
|
def describe
|
1121
1122
|
'('+@role_refs.map(&:describe)*', '+')'
|
1122
1123
|
end
|
@@ -1132,13 +1133,13 @@ module ActiveFacts
|
|
1132
1133
|
def ordinal; 0; end
|
1133
1134
|
|
1134
1135
|
def expand
|
1135
|
-
|
1136
|
-
|
1137
|
-
|
1138
|
-
|
1139
|
-
|
1140
|
-
|
1141
|
-
|
1136
|
+
text.gsub(/\{([01])\}/) do
|
1137
|
+
if $1 == '0'
|
1138
|
+
fact_type.all_role[0].object_type.name
|
1139
|
+
else
|
1140
|
+
fact_type.implying_role.object_type.name
|
1141
|
+
end
|
1142
|
+
end
|
1142
1143
|
end
|
1143
1144
|
end
|
1144
1145
|
end
|
@@ -1260,33 +1261,33 @@ module ActiveFacts
|
|
1260
1261
|
# It's an entity that's not an objectified fact type
|
1261
1262
|
|
1262
1263
|
# If it has a simple identifier, there's no need to fully verbalise the identifying facts.
|
1263
|
-
|
1264
|
-
|
1265
|
-
|
1266
|
-
|
1267
|
-
|
1268
|
-
|
1269
|
-
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
|
1275
|
-
|
1276
|
-
|
1277
|
-
|
1278
|
-
|
1279
|
-
|
1280
|
-
|
1281
|
-
|
1282
|
-
|
1283
|
-
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
|
1264
|
+
# This recursive block returns either the identifying value or nil
|
1265
|
+
simple_identifier = proc do |instance|
|
1266
|
+
if instance.object_type.is_a?(ActiveFacts::Metamodel::ValueType)
|
1267
|
+
instance
|
1268
|
+
else
|
1269
|
+
pi = instance.object_type.preferred_identifier
|
1270
|
+
identifying_role_refs = pi.role_sequence.all_role_ref_in_order
|
1271
|
+
if identifying_role_refs.size != 1
|
1272
|
+
nil
|
1273
|
+
else
|
1274
|
+
role = identifying_role_refs[0].role
|
1275
|
+
my_role = (role.fact_type.all_role.to_a-[role])[0]
|
1276
|
+
identifying_fact = my_role.all_role_value.detect{|rv| rv.instance == self}.fact
|
1277
|
+
irv = identifying_fact.all_role_value.detect{|rv| rv.role == role}
|
1278
|
+
identifying_instance = irv.instance
|
1279
|
+
simple_identifier.call(identifying_instance)
|
1280
|
+
end
|
1281
|
+
end
|
1282
|
+
end
|
1283
|
+
|
1284
|
+
if (id = simple_identifier.call(self))
|
1285
|
+
"#{object_type.name} #{id.value}"
|
1286
|
+
else
|
1287
|
+
pi = object_type.preferred_identifier
|
1288
|
+
identifying_role_refs = pi.role_sequence.all_role_ref_in_order
|
1289
|
+
"#{object_type.name}" +
|
1290
|
+
" is identified by " + # REVISIT: Where the single fact type is TypeInheritance, we can shrink this
|
1290
1291
|
identifying_role_refs.map do |rr|
|
1291
1292
|
rr = rr.preferred_reference
|
1292
1293
|
[ (l = rr.leading_adjective) ? l+"-" : nil,
|
@@ -1302,40 +1303,40 @@ module ActiveFacts
|
|
1302
1303
|
#identifying_instance = counterpart_role.all_role_value.detect{|rv| rv.fact == identifying_fact}.instance
|
1303
1304
|
identifying_fact.verbalise(context)
|
1304
1305
|
end*", "
|
1305
|
-
|
1306
|
+
end
|
1306
1307
|
|
1307
1308
|
end
|
1308
1309
|
end
|
1309
1310
|
|
1310
1311
|
class ContextNote
|
1311
1312
|
def verbalise(context=nil)
|
1312
|
-
|
1313
|
+
as_cql
|
1313
1314
|
end
|
1314
1315
|
|
1315
1316
|
def as_cql
|
1316
|
-
|
1317
|
-
|
1318
|
-
|
1319
|
-
|
1320
|
-
|
1321
|
-
|
1322
|
-
|
1323
|
-
|
1324
|
-
|
1325
|
-
|
1326
|
-
|
1327
|
-
|
1328
|
-
|
1329
|
-
|
1330
|
-
|
1331
|
-
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
|
1338
|
-
|
1317
|
+
' (' +
|
1318
|
+
( if all_context_according_to
|
1319
|
+
'according to '
|
1320
|
+
all_context_according_to.map do |act|
|
1321
|
+
act.agent.agent_name+', '
|
1322
|
+
end.join('')
|
1323
|
+
end
|
1324
|
+
) +
|
1325
|
+
context_note_kind.gsub(/_/, ' ') +
|
1326
|
+
' ' +
|
1327
|
+
discussion +
|
1328
|
+
( if agreement
|
1329
|
+
', as agreed ' +
|
1330
|
+
(agreement.date ? ' on '+agreement.date.iso8601.inspect+' ' : '') +
|
1331
|
+
'by '
|
1332
|
+
agreement.all_context_agreed_by.map do |acab|
|
1333
|
+
acab.agent.agent_name+', '
|
1334
|
+
end.join('')
|
1335
|
+
else
|
1336
|
+
''
|
1337
|
+
end
|
1338
|
+
) +
|
1339
|
+
')'
|
1339
1340
|
end
|
1340
1341
|
end
|
1341
1342
|
|