activefacts 1.1.0 → 1.2.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/bin/cql +137 -91
- data/css/style.css +3 -3
- data/examples/CQL/Insurance.cql +1 -1
- data/examples/CQL/SeparateSubtype.cql +2 -2
- data/lib/activefacts/cql/Language/English.treetop +9 -0
- data/lib/activefacts/cql/ObjectTypes.treetop +1 -1
- data/lib/activefacts/cql/Terms.treetop +3 -1
- data/lib/activefacts/cql/ValueTypes.treetop +10 -4
- data/lib/activefacts/cql/compiler.rb +1 -0
- data/lib/activefacts/cql/compiler/clause.rb +53 -23
- data/lib/activefacts/cql/compiler/entity_type.rb +0 -4
- data/lib/activefacts/cql/compiler/expression.rb +9 -13
- data/lib/activefacts/cql/compiler/fact.rb +49 -48
- data/lib/activefacts/cql/compiler/fact_type.rb +23 -20
- data/lib/activefacts/cql/compiler/query.rb +49 -121
- data/lib/activefacts/cql/compiler/shared.rb +5 -1
- data/lib/activefacts/cql/compiler/value_type.rb +4 -2
- data/lib/activefacts/generate/rails/schema.rb +138 -108
- data/lib/activefacts/generate/transform/surrogate.rb +1 -2
- data/lib/activefacts/mapping/rails.rb +52 -45
- data/lib/activefacts/persistence/columns.rb +5 -5
- data/lib/activefacts/persistence/tables.rb +6 -4
- data/lib/activefacts/support.rb +0 -2
- data/lib/activefacts/version.rb +1 -1
- data/lib/activefacts/vocabulary/extensions.rb +64 -42
- data/lib/activefacts/vocabulary/metamodel.rb +14 -12
- data/lib/activefacts/vocabulary/verbaliser.rb +98 -92
- data/spec/cql/expressions_spec.rb +8 -3
- data/spec/cql/parser/entity_types_spec.rb +1 -1
- data/spec/cql/parser/expressions_spec.rb +66 -52
- data/spec/cql/parser/fact_types_spec.rb +1 -1
- data/spec/cql/parser/literals_spec.rb +10 -10
- data/spec/cql/parser/pragmas_spec.rb +3 -3
- data/spec/cql/parser/value_types_spec.rb +1 -1
- metadata +2 -2
@@ -37,8 +37,8 @@ module ActiveFacts
|
|
37
37
|
to_s
|
38
38
|
end
|
39
39
|
|
40
|
-
def inspect
|
41
|
-
to_s
|
40
|
+
def inspect
|
41
|
+
to_s
|
42
42
|
end
|
43
43
|
|
44
44
|
def to_s phrases = nil
|
@@ -52,21 +52,34 @@ module ActiveFacts
|
|
52
52
|
# else 'definitely '
|
53
53
|
end
|
54
54
|
}#{
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
55
|
+
(
|
56
|
+
phrases.map do |phrase|
|
57
|
+
case phrase
|
58
|
+
when String
|
59
|
+
'"' + phrase.to_s + '"'
|
60
|
+
when Reference
|
61
|
+
phrase.to_s +
|
62
|
+
if phrase.nested_clauses
|
63
|
+
' (in which ' +
|
64
|
+
phrase.nested_clauses.map do |c|
|
65
|
+
((j = c.conjunction) ? j+' ' : '') +
|
66
|
+
c.to_s
|
67
|
+
end*' ' +
|
68
|
+
')'
|
69
|
+
else
|
70
|
+
''
|
71
|
+
end
|
72
|
+
when Operation
|
73
|
+
phrase.inspect
|
74
|
+
when Literal
|
75
|
+
phrase.inspect
|
76
|
+
#when FunctionCallChain # REVISIT: Add something here when I re-add functions
|
77
|
+
# phrase.inspect
|
78
|
+
else
|
79
|
+
raise "Unexpected phrase type in clause: #{phrase.class}"
|
80
|
+
end
|
81
|
+
end * ' '
|
82
|
+
).gsub(/" "/, ' ')
|
70
83
|
}#{
|
71
84
|
@context_note && ' ' + @context_note.inspect
|
72
85
|
}"
|
@@ -131,6 +144,22 @@ module ActiveFacts
|
|
131
144
|
def match_existing_fact_type context, options = {}
|
132
145
|
raise "Cannot match a clause that contains no object types" if refs.size == 0
|
133
146
|
raise "Internal error, clause already matched, should not match again" if @fact_type
|
147
|
+
|
148
|
+
if is_naked_object_type
|
149
|
+
ref = refs[0] # "There can be only one"
|
150
|
+
return true unless ref.nested_clauses
|
151
|
+
ref.nested_clauses.each do |nested|
|
152
|
+
ft = nested.match_existing_fact_type(context)
|
153
|
+
raise "Unrecognised fact type #{nested.display} nested under #{inspect}" unless ft
|
154
|
+
if (ft.entity_type == ref.player)
|
155
|
+
ref.objectification_of = ft
|
156
|
+
nested.objectified_as = ref
|
157
|
+
end
|
158
|
+
end
|
159
|
+
raise "#{ref.inspect} contains objectification steps that do not objectify it" unless ref.objectification_of
|
160
|
+
return true
|
161
|
+
end
|
162
|
+
|
134
163
|
# If we fail to match, try a left contraction (or save this for a subsequent left contraction):
|
135
164
|
left_contract_this_onto = context.left_contractable_clause
|
136
165
|
new_conjunction = (conjunction == nil || conjunction == ',')
|
@@ -195,7 +224,7 @@ module ActiveFacts
|
|
195
224
|
|
196
225
|
player_names = players.map{|p| p.name}
|
197
226
|
|
198
|
-
trace :matching, "Looking for existing #{players.size}-ary fact types matching '#{inspect
|
227
|
+
trace :matching, "Looking for existing #{players.size}-ary fact types matching '#{inspect}'" do
|
199
228
|
trace :matching, "Players are '#{player_names.inspect}'"
|
200
229
|
|
201
230
|
# Match existing fact types in nested clauses first:
|
@@ -204,12 +233,12 @@ module ActiveFacts
|
|
204
233
|
vrs.each do |ref|
|
205
234
|
next if ref.is_a?(Operation)
|
206
235
|
next unless steps = ref.nested_clauses and !steps.empty?
|
207
|
-
ref.nested_clauses.each do |
|
208
|
-
ft =
|
209
|
-
raise "Unrecognised fact type #{
|
236
|
+
ref.nested_clauses.each do |nested|
|
237
|
+
ft = nested.match_existing_fact_type(context)
|
238
|
+
raise "Unrecognised fact type #{nested.display}" unless ft
|
210
239
|
if (ft && ft.entity_type == ref.player)
|
211
240
|
ref.objectification_of = ft
|
212
|
-
|
241
|
+
nested.objectified_as = ref
|
213
242
|
end
|
214
243
|
end
|
215
244
|
raise "#{ref.inspect} contains objectification steps that do not objectify it" unless ref.objectification_of
|
@@ -883,7 +912,7 @@ module ActiveFacts
|
|
883
912
|
end
|
884
913
|
|
885
914
|
def includes_literals
|
886
|
-
@nested_clauses && @nested_clauses.detect{|
|
915
|
+
@nested_clauses && @nested_clauses.detect{|nested| nested.includes_literals}
|
887
916
|
end
|
888
917
|
|
889
918
|
# We create value types for the results of arithmetic expressions, and they get assigned here:
|
@@ -1064,6 +1093,7 @@ module ActiveFacts
|
|
1064
1093
|
end
|
1065
1094
|
end
|
1066
1095
|
|
1096
|
+
# REVISIT: This needs to handle annotations for some/that/which, etc.
|
1067
1097
|
class Quantifier
|
1068
1098
|
attr_accessor :enforcement
|
1069
1099
|
attr_accessor :context_note
|
@@ -170,10 +170,6 @@ module ActiveFacts
|
|
170
170
|
end
|
171
171
|
|
172
172
|
def create_identifying_fact_type context, clauses
|
173
|
-
# Remove uninteresting assertions:
|
174
|
-
clauses.reject!{|clause| clause.is_existential_type }
|
175
|
-
return nil unless clauses.size > 0 # Nothing interesting was said.
|
176
|
-
|
177
173
|
# See if any fact type already exists (this ET cannot be a player, but might objectify it)
|
178
174
|
existing_clauses = clauses.select{ |clause| clause.match_existing_fact_type context }
|
179
175
|
if negation = existing_clauses.detect{|c| c.certainty == false }
|
@@ -137,10 +137,6 @@ module ActiveFacts
|
|
137
137
|
@fact_type
|
138
138
|
end
|
139
139
|
|
140
|
-
def is_existential_type
|
141
|
-
false
|
142
|
-
end
|
143
|
-
|
144
140
|
def is_equality_comparison
|
145
141
|
false
|
146
142
|
end
|
@@ -179,7 +175,7 @@ module ActiveFacts
|
|
179
175
|
end
|
180
176
|
|
181
177
|
def result_type_name(context)
|
182
|
-
"
|
178
|
+
"COMPARE#{operator}<#{[@e1,@e2].map{|e| e.player.name}*' WITH '})>"
|
183
179
|
end
|
184
180
|
|
185
181
|
def is_equality_comparison
|
@@ -210,7 +206,7 @@ module ActiveFacts
|
|
210
206
|
def inspect; to_s; end
|
211
207
|
|
212
208
|
def to_s
|
213
|
-
"
|
209
|
+
"COMPARE#{
|
214
210
|
operator
|
215
211
|
}(#{
|
216
212
|
case @certainty
|
@@ -220,7 +216,7 @@ module ActiveFacts
|
|
220
216
|
end
|
221
217
|
}#{
|
222
218
|
e1.to_s
|
223
|
-
} #{
|
219
|
+
} WITH #{
|
224
220
|
e2.to_s
|
225
221
|
}#{
|
226
222
|
@qualifiers.empty? ? '' : ', ['+@qualifiers*', '+']'
|
@@ -255,7 +251,7 @@ module ActiveFacts
|
|
255
251
|
end
|
256
252
|
|
257
253
|
def result_type_name(context)
|
258
|
-
"
|
254
|
+
"SUM_OF<#{ @terms.map{|f| f.player.name}*', ' }>"
|
259
255
|
end
|
260
256
|
|
261
257
|
=begin
|
@@ -269,7 +265,7 @@ module ActiveFacts
|
|
269
265
|
def inspect; to_s; end
|
270
266
|
|
271
267
|
def to_s
|
272
|
-
'
|
268
|
+
'SUM(' + @terms.map{|term| "#{term.to_s}" } * ' PLUS ' + ')'
|
273
269
|
end
|
274
270
|
end
|
275
271
|
|
@@ -299,7 +295,7 @@ module ActiveFacts
|
|
299
295
|
end
|
300
296
|
|
301
297
|
def result_type_name(context)
|
302
|
-
"
|
298
|
+
"PRODUCT_OF<#{ @factors.map{|f| f.player.name}*' ' }>"
|
303
299
|
end
|
304
300
|
|
305
301
|
=begin
|
@@ -313,7 +309,7 @@ module ActiveFacts
|
|
313
309
|
def inspect; to_s; end
|
314
310
|
|
315
311
|
def to_s
|
316
|
-
'
|
312
|
+
'PRODUCT(' + @factors.map{|factor| "#{factor.to_s}" } * ' TIMES ' + ')'
|
317
313
|
end
|
318
314
|
end
|
319
315
|
|
@@ -350,7 +346,7 @@ module ActiveFacts
|
|
350
346
|
def inspect; to_s; end
|
351
347
|
|
352
348
|
def to_s
|
353
|
-
"
|
349
|
+
"RECIPROCAL(#{factor.to_s})"
|
354
350
|
end
|
355
351
|
end
|
356
352
|
|
@@ -381,7 +377,7 @@ module ActiveFacts
|
|
381
377
|
def inspect; to_s; end
|
382
378
|
|
383
379
|
def to_s
|
384
|
-
"
|
380
|
+
"NEGATIVE(#{term.to_s})"
|
385
381
|
end
|
386
382
|
end
|
387
383
|
|
@@ -24,7 +24,7 @@ module ActiveFacts
|
|
24
24
|
|
25
25
|
# Figure out the simple existential facts and find fact types:
|
26
26
|
@bound_facts = []
|
27
|
-
@unbound_clauses = all_clauses.
|
27
|
+
@unbound_clauses = all_clauses(@clauses).
|
28
28
|
map do |clause|
|
29
29
|
bind_literal_or_fact_type clause
|
30
30
|
end.
|
@@ -53,7 +53,7 @@ module ActiveFacts
|
|
53
53
|
player = ref.binding.player
|
54
54
|
# raise "A literal may not be an objectification" if ref.role_ref.nested_clauses
|
55
55
|
# raise "Not processing facts involving nested clauses yet" if ref.role_ref
|
56
|
-
trace :
|
56
|
+
trace :instance_detail, "Making #{player.class.basename} #{player.name} using #{l.inspect}" do
|
57
57
|
ref.binding.instance = instance_identified_by_literal(player, l)
|
58
58
|
end
|
59
59
|
ref
|
@@ -92,8 +92,8 @@ module ActiveFacts
|
|
92
92
|
true
|
93
93
|
end
|
94
94
|
|
95
|
-
|
96
|
-
|
95
|
+
trace :instance_detail, "Considering '#{clause.display}' with "+
|
96
|
+
(bare_roles.empty? ? "no bare roles" : "bare roles: #{bare_roles.map{|ref| ref.player.name}*", "}") do
|
97
97
|
|
98
98
|
# If all the roles are in place, we can bind the rest of this clause:
|
99
99
|
return true if bare_roles.size == 0 && bind_complete_fact(clause)
|
@@ -109,7 +109,7 @@ module ActiveFacts
|
|
109
109
|
end
|
110
110
|
|
111
111
|
return true if progress
|
112
|
-
trace :
|
112
|
+
trace :instance_detail, "Delaying until all role players are asserted: #{clause.fact_type.default_reading.inspect}"
|
113
113
|
nil
|
114
114
|
end
|
115
115
|
end
|
@@ -120,37 +120,36 @@ module ActiveFacts
|
|
120
120
|
@pass += 1
|
121
121
|
|
122
122
|
progress = false
|
123
|
-
trace :
|
123
|
+
trace :instance_detail, "Pass #{@pass} with #{@unbound_clauses.size} clauses to consider" do
|
124
124
|
@unbound_clauses =
|
125
125
|
@unbound_clauses.select do |clause|
|
126
126
|
action = bind_clause(clause)
|
127
127
|
progress = true if action
|
128
128
|
!action
|
129
129
|
end
|
130
|
-
trace :
|
130
|
+
trace :instance_detail, "end of pass, unbound clauses are #{@unbound_clauses.map(&:display)*', '}"
|
131
131
|
end # debug
|
132
132
|
progress
|
133
133
|
end
|
134
134
|
|
135
|
-
# Occasionally we need to search through all the clauses
|
136
|
-
def all_clauses
|
137
|
-
|
138
|
-
[clause] + clause.refs.map{|vr| vr.nested_clauses}
|
135
|
+
# Occasionally we need to search through all the clauses. This builds a flat list
|
136
|
+
def all_clauses clauses
|
137
|
+
clauses.map do |clause|
|
138
|
+
[clause] + clause.refs.map{|vr| vr.nested_clauses ? all_clauses(vr.nested_clauses) : []}
|
139
139
|
end.flatten.compact
|
140
140
|
end
|
141
141
|
|
142
142
|
def bind_complete_fact clause
|
143
143
|
return true unless clause.fact_type # An bare objectification
|
144
|
-
trace :instance, "All bindings in '#{clause.display}' contain instances; assert the fact type"
|
145
144
|
instances = clause.refs.map{|vr| vr.binding.instance }
|
146
|
-
trace :
|
145
|
+
trace :instance_detail, "All role players exist for #{clause.display.inspect} exist: #{instances.map{|i| "#{i.verbalise}"}*", "}"
|
147
146
|
|
148
147
|
if e = clause.fact_type.entity_type and
|
149
148
|
clause.refs[0].binding.instance.object_type == e
|
150
149
|
fact = clause.refs[0].binding.instance.fact
|
151
150
|
else
|
152
151
|
# Check that this fact doesn't already exist
|
153
|
-
trace :
|
152
|
+
trace :instance_detail, "Searching for existing fact instance"
|
154
153
|
|
155
154
|
fact = clause.fact_type.all_fact.detect do |f|
|
156
155
|
|
@@ -165,26 +164,27 @@ module ActiveFacts
|
|
165
164
|
end
|
166
165
|
if fact
|
167
166
|
clause.fact = fact
|
168
|
-
trace :instance, "
|
167
|
+
trace :instance, "Already known: #{fact.verbalise.inspect}"
|
169
168
|
else
|
170
|
-
trace :
|
169
|
+
trace :instance_detail, "Asserting fact of type #{clause.fact_type.default_reading.inspect}"
|
171
170
|
fact =
|
172
171
|
clause.fact =
|
173
172
|
@constellation.Fact(:new, :fact_type => clause.fact_type, :population => @population)
|
174
173
|
@bound_facts << fact
|
175
174
|
clause.reading.role_sequence.all_role_ref_in_order.zip(instances).each do |rr, instance|
|
176
|
-
trace :
|
175
|
+
trace :instance_detail, "Assigning fact role #{instance.object_type.name} to #{instance.value ? instance.value.inspect : instance.verbalise}"
|
177
176
|
# REVISIT: Any residual adjectives after the fact type matching are lost here.
|
178
177
|
@constellation.RoleValue(:fact => fact, :instance => instance, :role => rr.role, :population => @population)
|
179
178
|
end
|
179
|
+
trace :instance, "Assert #{fact.verbalise.inspect} #{@population.name.size>0 ? " in "+@population.name.inspect : ''}" unless clause.fact_type.entity_type
|
180
180
|
end
|
181
181
|
|
182
182
|
if !fact.instance && clause.fact_type.entity_type
|
183
183
|
# Objectified fact type; create the instance
|
184
184
|
# Create the instance that objectifies this fact. We don't have the binding to assign it to though; that'll happen in our caller
|
185
|
-
trace :instance, "Objectifying fact as #{clause.fact_type.entity_type.name}"
|
186
185
|
instance =
|
187
186
|
@constellation.Instance(:new, :object_type => clause.fact_type.entity_type, :fact => fact, :population => @population)
|
187
|
+
trace :instance, "Assert #{instance.verbalise.inspect}"
|
188
188
|
@bound_facts << instance
|
189
189
|
end
|
190
190
|
|
@@ -207,23 +207,24 @@ module ActiveFacts
|
|
207
207
|
return false unless identifying_binding # This happens when we have a bare objectification
|
208
208
|
identifying_instance = identifying_binding.instance
|
209
209
|
preferred_identifier = entity_type.preferred_identifier
|
210
|
+
role_count = preferred_identifier.role_sequence.all_role_ref.size
|
210
211
|
|
211
|
-
trace :instance, "
|
212
|
+
trace :instance, "A #{binding.player.name} is #{role_count > 1 ? 'partly ':''}identified in #{clause.inspect}"
|
212
213
|
|
213
214
|
identifying_role_ref = preferred_identifier.role_sequence.all_role_ref.detect { |rr|
|
214
215
|
rr.role.fact_type == clause.fact_type && rr.role.object_type == identifying_binding.player
|
215
216
|
}
|
216
217
|
unless identifying_role_ref
|
217
|
-
# This
|
218
|
+
# This should never happen; we already bound all refs
|
218
219
|
trace :instance, "Failed to find a #{identifying_instance.object_type.name}"
|
219
220
|
return false # We can't do this yet
|
220
221
|
end
|
221
222
|
role_value = identifying_instance.all_role_value.detect do |rv|
|
222
223
|
rv.fact.fact_type == identifying_role_ref.role.fact_type
|
223
224
|
end
|
224
|
-
if role_value
|
225
|
+
if role_value && role_count == 1
|
225
226
|
instance = (role_value.fact.all_role_value.to_a-[role_value])[0].instance
|
226
|
-
trace :instance, "
|
227
|
+
trace :instance, "Existential fact already known: #{instance.verbalise.inspect}"
|
227
228
|
binding.instance = instance
|
228
229
|
return true # Done with this clause
|
229
230
|
end
|
@@ -234,7 +235,7 @@ module ActiveFacts
|
|
234
235
|
identifiers =
|
235
236
|
pi_role_refs.map do |rr|
|
236
237
|
# Find a clause that provides the identifying_ref for this player:
|
237
|
-
identifying_clause = all_clauses.detect do |clause|
|
238
|
+
identifying_clause = all_clauses(@clauses).detect do |clause|
|
238
239
|
rr.role.fact_type == clause.fact_type &&
|
239
240
|
clause.refs.detect{|vr| vr.binding == binding}
|
240
241
|
end
|
@@ -250,22 +251,21 @@ module ActiveFacts
|
|
250
251
|
return false
|
251
252
|
end
|
252
253
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
end
|
254
|
+
instance = @constellation.Instance(:new, :object_type => entity_type, :population => @population)
|
255
|
+
binding.instance = instance
|
256
|
+
@bound_facts << instance
|
257
|
+
identifiers.each do |rr, identifying_clause, identifying_binding, identifying_instance|
|
258
|
+
# This clause provides the identifying literal for the entity_type
|
259
|
+
id_fact =
|
260
|
+
identifying_clause.fact =
|
261
|
+
@constellation.Fact(:new, :fact_type => rr.role.fact_type, :population => @population)
|
262
|
+
@bound_facts << id_fact
|
263
|
+
role = (rr.role.fact_type.all_role.to_a-[rr.role])[0]
|
264
|
+
@constellation.RoleValue(:instance => instance, :fact => id_fact, :population => @population, :role => role)
|
265
|
+
@constellation.RoleValue(:instance => identifying_instance, :fact => id_fact, :role => rr.role, :population => @population)
|
266
|
+
trace :instance, "Assert #{id_fact.verbalise.inspect} (existential) #{@population.name.size>0 ? " in "+@population.name.inspect : ''}"
|
267
|
+
end
|
268
|
+
trace :instance, "Assert #{instance.verbalise.inspect} #{@population.name.size>0 ? " in "+@population.name.inspect : ''}"
|
269
269
|
|
270
270
|
true # Done with this clause
|
271
271
|
end
|
@@ -274,29 +274,29 @@ module ActiveFacts
|
|
274
274
|
if object_type.is_a?(ActiveFacts::Metamodel::EntityType)
|
275
275
|
entity_identified_by_literal object_type, literal
|
276
276
|
else
|
277
|
-
trace :
|
277
|
+
trace :instance_detail, "Assert Value #{object_type.name} #{literal.inspect}" do
|
278
278
|
is_literal_string = literal.literal.is_a?(String)
|
279
279
|
# REVISIT: Check for subtypes and supertypes also, and promote type if necessary
|
280
280
|
instance = object_type.all_instance.detect do |i|
|
281
281
|
#instance = @constellation.Instance.detect do |key, i|
|
282
282
|
# REVISIT: And same unit
|
283
|
-
trace :
|
283
|
+
trace :instance_detail2, "Comparing #{i.value.literal.inspect} to #{literal.literal.to_s.inspect}"
|
284
284
|
i.population == @population &&
|
285
285
|
i.value &&
|
286
|
-
i.value.literal.inspect == literal.literal.inspect &&
|
286
|
+
i.value.literal.inspect == literal.literal.to_s.inspect &&
|
287
287
|
i.value.is_literal_string == is_literal_string
|
288
288
|
end
|
289
289
|
#instance = object_type.all_instance.detect { |instance|
|
290
290
|
# instance.population == @population && instance.value == literal
|
291
291
|
#}
|
292
292
|
if instance
|
293
|
-
trace :instance, "
|
293
|
+
trace :instance, "Instance already known: #{instance.verbalise.inspect}"
|
294
294
|
else
|
295
|
-
trace :instance, "Creating Value #{object_type.name} #{literal.inspect} #{@population.name.size>0 ? " in "+@population.name.inspect : ''}"
|
296
295
|
instance = @constellation.Instance(:new)
|
297
296
|
instance.object_type = object_type
|
298
297
|
instance.population = @population
|
299
298
|
instance.value = [literal.to_s, is_literal_string, nil]
|
299
|
+
trace :instance, "Assert #{instance.verbalise.inspect} #{@population.name.size>0 ? " in "+@population.name.inspect : ''}"
|
300
300
|
@bound_facts << instance
|
301
301
|
end
|
302
302
|
instance
|
@@ -307,7 +307,7 @@ module ActiveFacts
|
|
307
307
|
def entity_identified_by_literal object_type, literal
|
308
308
|
# A literal that identifies an entity type means the entity type has only one identifying role
|
309
309
|
# That role is played either by a value type, or by another similarly single-identified entity type
|
310
|
-
trace :
|
310
|
+
trace :instance_detail, "Assert Entity #{object_type.name} identified by '#{literal}'" do
|
311
311
|
identifying_role_refs = object_type.preferred_identifier.role_sequence.all_role_ref
|
312
312
|
raise "Single literal cannot satisfy multiple identifying roles for #{object_type.name}" if identifying_role_refs.size > 1
|
313
313
|
role = identifying_role_refs.single.role
|
@@ -323,19 +323,20 @@ module ActiveFacts
|
|
323
323
|
}
|
324
324
|
if instance_rv
|
325
325
|
instance = existing_instance
|
326
|
-
|
326
|
+
trace :instance, "Already known: #{instance.verbalise.inspect}"
|
327
327
|
else
|
328
328
|
# This fact has no clause.
|
329
|
-
trace :
|
329
|
+
trace :instance_detail, "Creating implicit existential fact #{role.fact_type.default_reading}"
|
330
330
|
fact = @constellation.Fact(:new, :fact_type => role.fact_type, :population => @population)
|
331
331
|
@bound_facts << fact
|
332
332
|
# This instance will be associated with its binding by our caller
|
333
333
|
instance = @constellation.Instance(:new, :object_type => object_type, :population => @population)
|
334
|
-
trace :
|
334
|
+
trace :instance_detail, "Creating Entity #{object_type.name} identified by '#{literal}' #{@population.name.size>0 ? " in "+@population.name.inspect : ''}"
|
335
335
|
@bound_facts << instance
|
336
336
|
# The identifying fact type has two roles; create both role instances:
|
337
337
|
@constellation.RoleValue(:instance => identifying_instance, :fact => fact, :population => @population, :role => role)
|
338
338
|
@constellation.RoleValue(:instance => instance, :fact => fact, :population => @population, :role => (role.fact_type.all_role-[role])[0])
|
339
|
+
trace :instance, "Assert #{instance.verbalise.inspect}"
|
339
340
|
end
|
340
341
|
instance
|
341
342
|
end
|