activefacts 1.0.2 → 1.1.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.
Files changed (47) hide show
  1. checksums.yaml +5 -13
  2. data/Rakefile +2 -2
  3. data/bin/afgen +1 -1
  4. data/bin/cql +118 -27
  5. data/examples/CQL/Insurance.cql +2 -2
  6. data/examples/CQL/Metamodel.cql +3 -3
  7. data/examples/CQL/SchoolActivities.cql +1 -1
  8. data/examples/CQL/Warehousing.cql +5 -4
  9. data/lib/activefacts/cql.rb +1 -1
  10. data/lib/activefacts/cql/Language/English.treetop +2 -1
  11. data/lib/activefacts/cql/compiler.rb +6 -6
  12. data/lib/activefacts/cql/compiler/clause.rb +69 -46
  13. data/lib/activefacts/cql/compiler/constraint.rb +14 -14
  14. data/lib/activefacts/cql/compiler/entity_type.rb +24 -24
  15. data/lib/activefacts/cql/compiler/fact.rb +40 -27
  16. data/lib/activefacts/cql/compiler/fact_type.rb +16 -16
  17. data/lib/activefacts/cql/compiler/query.rb +12 -12
  18. data/lib/activefacts/cql/compiler/shared.rb +9 -0
  19. data/lib/activefacts/cql/compiler/value_type.rb +4 -4
  20. data/lib/activefacts/cql/parser.rb +9 -9
  21. data/lib/activefacts/generate/cql.rb +41 -20
  22. data/lib/activefacts/generate/helpers/oo.rb +33 -70
  23. data/lib/activefacts/generate/helpers/ordered.rb +61 -87
  24. data/lib/activefacts/generate/ruby.rb +12 -72
  25. data/lib/activefacts/generate/transform/surrogate.rb +13 -13
  26. data/lib/activefacts/input/orm.rb +72 -71
  27. data/lib/activefacts/persistence/columns.rb +66 -31
  28. data/lib/activefacts/persistence/foreignkey.rb +6 -6
  29. data/lib/activefacts/persistence/index.rb +12 -12
  30. data/lib/activefacts/persistence/object_type.rb +15 -12
  31. data/lib/activefacts/persistence/reference.rb +20 -18
  32. data/lib/activefacts/persistence/tables.rb +40 -36
  33. data/lib/activefacts/support.rb +69 -123
  34. data/lib/activefacts/version.rb +2 -2
  35. data/lib/activefacts/vocabulary/extensions.rb +42 -39
  36. data/lib/activefacts/vocabulary/metamodel.rb +11 -1
  37. data/lib/activefacts/vocabulary/verbaliser.rb +28 -28
  38. data/spec/cql/contractions_spec.rb +1 -1
  39. data/spec/cql/entity_type_spec.rb +1 -1
  40. data/spec/cql/fact_type_matching_spec.rb +3 -3
  41. data/spec/cql/role_matching_spec.rb +4 -4
  42. data/spec/cql/samples_spec.rb +2 -2
  43. data/spec/cql_cql_spec.rb +1 -1
  44. data/spec/helpers/array_matcher.rb +1 -1
  45. data/spec/norma_ruby_sql_spec.rb +2 -2
  46. data/spec/norma_tables_spec.rb +3 -2
  47. metadata +47 -68
@@ -105,13 +105,13 @@ module ActiveFacts
105
105
 
106
106
  def loose_bind_wherever_possible
107
107
  # Apply loose binding over applicable roles:
108
- debug :binding, "Loose binding on #{self.class.name}" do
108
+ trace :binding, "Loose binding on #{self.class.name}" do
109
109
  @clauses_lists.each do |clauses_list|
110
110
  clauses_list.each do |clause|
111
111
  clause.refs.each_with_index do |ref, i|
112
112
  next if ref.binding.refs.size > 1
113
113
  # if clause.side_effects && !clause.side_effects.role_side_effects[i].residual_adjectives
114
- # debug :binding, "Discounting #{ref.inspect} as needing loose binding because it has no residual_adjectives"
114
+ # trace :binding, "Discounting #{ref.inspect} as needing loose binding because it has no residual_adjectives"
115
115
  # next
116
116
  # end
117
117
  # This ref didn't match any other ref. Have a scout around for a suitable partner
@@ -128,7 +128,7 @@ module ActiveFacts
128
128
  }
129
129
  end.map{|k,b| b}
130
130
  next if candidates.size != 1 # Fail
131
- debug :binding, "Loose binding #{ref.inspect} to #{candidates[0].inspect}"
131
+ trace :binding, "Loose binding #{ref.inspect} to #{candidates[0].inspect}"
132
132
  ref.rebind_to(@context, candidates[0].refs[0])
133
133
  end
134
134
  end
@@ -138,15 +138,15 @@ module ActiveFacts
138
138
 
139
139
  def loose_bind
140
140
  # Apply loose binding over applicable @roles:
141
- debug :binding, "Check for loose bindings on #{@roles.size} roles in #{self.class.name}" do
141
+ trace :binding, "Check for loose bindings on #{@roles.size} roles in #{self.class.name}" do
142
142
  @roles.each do |ref|
143
143
  if ref.binding.refs.size < @clauses_lists.size+1
144
- debug :binding, "Insufficient bindings for #{ref.inspect} (#{ref.binding.refs.size}, expected #{@clauses_lists.size+1}), attempting loose binding" do
144
+ trace :binding, "Insufficient bindings for #{ref.inspect} (#{ref.binding.refs.size}, expected #{@clauses_lists.size+1}), attempting loose binding" do
145
145
  @clauses_lists.each do |clauses_list|
146
146
  candidates = []
147
147
  next if clauses_list.
148
148
  detect do |clause|
149
- debug :binding, "Checking #{clause.inspect}"
149
+ trace :binding, "Checking #{clause.inspect}"
150
150
  clause.refs.
151
151
  detect do |vr|
152
152
  already_bound = vr.binding == ref.binding
@@ -156,10 +156,10 @@ module ActiveFacts
156
156
  already_bound
157
157
  end
158
158
  end
159
- debug :binding, "Attempting loose binding for #{ref.inspect} in #{clauses_list.inspect}, from the following candidates: #{candidates.inspect}"
159
+ trace :binding, "Attempting loose binding for #{ref.inspect} in #{clauses_list.inspect}, from the following candidates: #{candidates.inspect}"
160
160
 
161
161
  if candidates.size == 1
162
- debug :binding, "Rebinding #{candidates[0].inspect} to #{ref.inspect}"
162
+ trace :binding, "Rebinding #{candidates[0].inspect} to #{ref.inspect}"
163
163
  candidates[0].rebind_to(@context, ref)
164
164
  end
165
165
  end
@@ -226,7 +226,7 @@ module ActiveFacts
226
226
  :is_mandatory => @quantifier.min && @quantifier.min > 0
227
227
  )
228
228
  @enforcement.compile(@constellation, @constraint) if @enforcement
229
- debug :constraint, "Made new PC GUID=#{@constraint.concept.guid} min=#{@quantifier.min.inspect} max=#{@quantifier.max.inspect} over #{role_sequence.describe}"
229
+ trace :constraint, "Made new PC GUID=#{@constraint.concept.guid} min=#{@quantifier.min.inspect} max=#{@quantifier.max.inspect} over #{role_sequence.describe}"
230
230
  super
231
231
  end
232
232
 
@@ -244,7 +244,7 @@ module ActiveFacts
244
244
  clause.refs.select{ |vr| vr.player == ref.player }
245
245
  end.flatten
246
246
  if candidates.size == 1
247
- debug :binding, "Rebinding #{ref.inspect} to #{candidates[0].inspect} in presence constraint"
247
+ trace :binding, "Rebinding #{ref.inspect} to #{candidates[0].inspect} in presence constraint"
248
248
  ref.rebind_to(@context, candidates[0])
249
249
  end
250
250
  end
@@ -276,8 +276,8 @@ module ActiveFacts
276
276
  clause.includes_literals
277
277
  end
278
278
 
279
- debug :query, "Building query for #{clauses_list.inspect}" do
280
- debug :query, "Constrained bindings are #{@common_bindings.inspect}"
279
+ trace :query, "Building query for #{clauses_list.inspect}" do
280
+ trace :query, "Constrained bindings are #{@common_bindings.inspect}"
281
281
  # Every Binding in these clauses becomes a Variable,
282
282
  # and every clause becomes a Step (and a RoleSequence).
283
283
  # The returned RoleSequences contains the RoleRefs for the common_bindings.
@@ -301,7 +301,7 @@ module ActiveFacts
301
301
  role_sequence = @constellation.RoleSequence(:new)
302
302
  query_bindings = bindings-@common_bindings
303
303
  unless query_bindings.empty? or ignore_trailing_steps && query_bindings.size <= 1
304
- debug :constraint, "REVISIT: #{self.class}: Ignoring query from #{@common_bindings.inspect} to #{query_bindings.inspect} in #{clauses_list.inspect}"
304
+ trace :constraint, "REVISIT: #{self.class}: Ignoring query from #{@common_bindings.inspect} to #{query_bindings.inspect} in #{clauses_list.inspect}"
305
305
  end
306
306
  @common_bindings.each do |binding|
307
307
  roles = clauses_list.
@@ -483,7 +483,7 @@ module ActiveFacts
483
483
  :ring_type => ring_type
484
484
  )
485
485
 
486
- debug :constraint, "Added #{@constraint.verbalise}"
486
+ trace :constraint, "Added #{@constraint.verbalise}"
487
487
  super
488
488
  end
489
489
 
@@ -122,7 +122,7 @@ module ActiveFacts
122
122
  if (pc)
123
123
  pc.is_preferred_identifier = true
124
124
  pc.name = "#{@entity_type.name}PK" unless pc.name
125
- debug "Existing PC #{pc.verbalise} is now PK for #{@entity_type.name}"
125
+ trace "Existing PC #{pc.verbalise} is now PK for #{@entity_type.name}"
126
126
  else
127
127
  # Add a unique constraint over all identifying roles
128
128
  pc = @constellation.PresenceConstraint(
@@ -135,7 +135,7 @@ module ActiveFacts
135
135
  #:is_mandatory => true,
136
136
  #:min_frequency => 1,
137
137
  )
138
- debug :constraint, "Made new preferred PC GUID=#{pc.concept.guid} min=nil max=1 over #{role_sequence.describe}"
138
+ trace :constraint, "Made new preferred PC GUID=#{pc.concept.guid} min=nil max=1 over #{role_sequence.describe}"
139
139
  end
140
140
  end
141
141
 
@@ -183,7 +183,7 @@ module ActiveFacts
183
183
 
184
184
  operation = any_matched ? 'Objectifying' : 'Creating'
185
185
  player_names = clauses[0].refs.map{|vr| vr.key.compact*'-'}
186
- debug :matching, "#{operation} fact type for #{clauses.size} clauses over (#{player_names*', '})" do
186
+ trace :matching, "#{operation} fact type for #{clauses.size} clauses over (#{player_names*', '})" do
187
187
  if any_matched # There's an existing fact type we must be objectifying
188
188
  fact_type = objectify_existing_fact_type(existing_clauses[0].fact_type)
189
189
  end
@@ -220,7 +220,7 @@ module ActiveFacts
220
220
  :is_preferred_identifier => false, # We only get here when there is a reference mode on the entity type
221
221
  :max_frequency => 1
222
222
  )
223
- debug :constraint, "Made new objectification PC GUID=#{pc.concept.guid} min=nil max=1 over #{fact_type.preferred_reading.role_sequence.describe}"
223
+ trace :constraint, "Made new objectification PC GUID=#{pc.concept.guid} min=nil max=1 over #{fact_type.preferred_reading.role_sequence.describe}"
224
224
  end
225
225
 
226
226
  @fact_type = @entity_type.fact_type = fact_type
@@ -229,7 +229,7 @@ module ActiveFacts
229
229
  end
230
230
 
231
231
  def add_supertype(supertype_name, not_identifying)
232
- debug :supertype, "Adding #{not_identifying ? '' : 'identifying '}supertype #{supertype_name} to #{@entity_type.name}" do
232
+ trace :supertype, "Adding #{not_identifying ? '' : 'identifying '}supertype #{supertype_name} to #{@entity_type.name}" do
233
233
  supertype = @vocabulary.valid_entity_type_name(supertype_name) ||
234
234
  @constellation.EntityType(@vocabulary, supertype_name, :concept => :new) # Should always already exist
235
235
 
@@ -275,7 +275,7 @@ module ActiveFacts
275
275
  pc1.min_frequency = 1
276
276
  pc1.max_frequency = 1
277
277
  pc1.is_preferred_identifier = false
278
- debug :constraint, "Made new subtype PC GUID=#{pc1.concept.guid} min=1 max=1 over #{p1rs.describe}"
278
+ trace :constraint, "Made new subtype PC GUID=#{pc1.concept.guid} min=1 max=1 over #{p1rs.describe}"
279
279
 
280
280
  p2rs = @constellation.RoleSequence(:new)
281
281
  constellation.RoleRef(p2rs, 0).role = super_role
@@ -287,15 +287,15 @@ module ActiveFacts
287
287
  pc2.max_frequency = 1
288
288
  # The supertype role often identifies the subtype:
289
289
  pc2.is_preferred_identifier = inheritance_fact.provides_identification
290
- debug :supertype, "identification of #{@entity_type.name} via supertype #{supertype.name} was #{inheritance_fact.provides_identification ? '' : 'not '}added"
291
- debug :constraint, "Made new supertype PC GUID=#{pc2.concept.guid} min=1 max=1 over #{p2rs.describe}"
290
+ trace :supertype, "identification of #{@entity_type.name} via supertype #{supertype.name} was #{inheritance_fact.provides_identification ? '' : 'not '}added"
291
+ trace :constraint, "Made new supertype PC GUID=#{pc2.concept.guid} min=1 max=1 over #{p2rs.describe}"
292
292
  end
293
293
  end
294
294
 
295
295
  def make_entity_type_refmode_valuetypes(name, mode, parameters)
296
296
  vt_name = "#{name}#{mode}"
297
297
  vt = nil
298
- debug :entity, "Preparing value type #{vt_name} for reference mode" do
298
+ trace :entity, "Preparing value type #{vt_name} for reference mode" do
299
299
  # Find an existing ValueType called 'vt_name' or 'name vtname'
300
300
  # or find/create the supertype '#{mode}' and the subtype
301
301
  unless vt = @vocabulary.valid_object_type_name(vt_name) or
@@ -309,7 +309,7 @@ module ActiveFacts
309
309
  vt.scale = scale if scale
310
310
  end
311
311
  else
312
- debug :entity, "Value type #{vt_name} already exists"
312
+ trace :entity, "Value type #{vt_name} already exists"
313
313
  end
314
314
  end
315
315
 
@@ -363,9 +363,9 @@ module ActiveFacts
363
363
  end
364
364
  if rs01.all_reading.empty?
365
365
  @constellation.Reading(fact_type, fact_type.all_reading.size, :role_sequence => rs01, :text => "{0} has {1}", :is_negative => false)
366
- debug :mode, "Creating new forward reading '#{entity_role.object_type.name} has #{identifying_type.name}'"
366
+ trace :mode, "Creating new forward reading '#{entity_role.object_type.name} has #{identifying_type.name}'"
367
367
  else
368
- debug :mode, "Using existing forward reading"
368
+ trace :mode, "Using existing forward reading"
369
369
  end
370
370
 
371
371
  # Make a reverse reading if none exists
@@ -377,20 +377,20 @@ module ActiveFacts
377
377
  end
378
378
  if rs10.all_reading.empty?
379
379
  @constellation.Reading(fact_type, fact_type.all_reading.size, :role_sequence => rs10, :text => "{0} is of {1}", :is_negative => false)
380
- debug :mode, "Creating new reverse reading '#{identifying_type.name} is of #{entity_role.object_type.name}'"
380
+ trace :mode, "Creating new reverse reading '#{identifying_type.name} is of #{entity_role.object_type.name}'"
381
381
  else
382
- debug :mode, "Using existing reverse reading"
382
+ trace :mode, "Using existing reverse reading"
383
383
  end
384
384
 
385
385
  # Entity must have one identifying instance. Find or create the role sequence, then create a PC if necessary
386
386
  rs0 = entity_role.all_role_ref.select{|rr| rr.role_sequence.all_role_ref.size == 1}[0]
387
387
  if rs0
388
388
  rs0 = rs0.role_sequence
389
- debug :mode, "Using existing EntityType role sequence"
389
+ trace :mode, "Using existing EntityType role sequence"
390
390
  else
391
391
  rs0 = @constellation.RoleSequence(:new)
392
392
  @constellation.RoleRef(rs0, 0, :role => entity_role)
393
- debug :mode, "Creating new EntityType role sequence"
393
+ trace :mode, "Creating new EntityType role sequence"
394
394
  end
395
395
  if (rs0.all_presence_constraint.size == 0)
396
396
  constraint = @constellation.PresenceConstraint(
@@ -403,22 +403,22 @@ module ActiveFacts
403
403
  :is_preferred_identifier => false,
404
404
  :is_mandatory => true
405
405
  )
406
- debug :constraint, "Made new refmode PC GUID=#{constraint.concept.guid} min=1 max=1 over #{rs0.describe}"
406
+ trace :constraint, "Made new refmode PC GUID=#{constraint.concept.guid} min=1 max=1 over #{rs0.describe}"
407
407
  else
408
- debug :mode, "Using existing EntityType PresenceConstraint"
408
+ trace :mode, "Using existing EntityType PresenceConstraint"
409
409
  end
410
410
 
411
411
  # Value Type must have a value type. Find or create the role sequence, then create a PC if necessary
412
- debug :mode, "identifying_role has #{identifying_role.all_role_ref.size} attached sequences"
413
- debug :mode, "identifying_role has #{identifying_role.all_role_ref.select{|rr| rr.role_sequence.all_role_ref.size == 1}.size} unary sequences"
412
+ trace :mode, "identifying_role has #{identifying_role.all_role_ref.size} attached sequences"
413
+ trace :mode, "identifying_role has #{identifying_role.all_role_ref.select{|rr| rr.role_sequence.all_role_ref.size == 1}.size} unary sequences"
414
414
  rs1 = identifying_role.all_role_ref.select{|rr| rr.role_sequence.all_role_ref.size == 1 ? rr.role_sequence : nil }.compact[0]
415
415
  if (!rs1)
416
416
  rs1 = @constellation.RoleSequence(:new)
417
417
  @constellation.RoleRef(rs1, 0, :role => identifying_role)
418
- debug :mode, "Creating new ValueType role sequence"
418
+ trace :mode, "Creating new ValueType role sequence"
419
419
  else
420
420
  rs1 = rs1.role_sequence
421
- debug :mode, "Using existing ValueType role sequence"
421
+ trace :mode, "Using existing ValueType role sequence"
422
422
  end
423
423
  if (rs1.all_presence_constraint.size == 0)
424
424
  constraint = @constellation.PresenceConstraint(
@@ -431,9 +431,9 @@ module ActiveFacts
431
431
  :is_preferred_identifier => true,
432
432
  :is_mandatory => false
433
433
  )
434
- debug :constraint, "Made new refmode ValueType PC GUID=#{constraint.concept.guid} min=0 max=1 over #{rs1.describe}"
434
+ trace :constraint, "Made new refmode ValueType PC GUID=#{constraint.concept.guid} min=0 max=1 over #{rs1.describe}"
435
435
  else
436
- debug :mode, "Marking existing ValueType PresenceConstraint as preferred"
436
+ trace :mode, "Marking existing ValueType PresenceConstraint as preferred"
437
437
  rs1.all_presence_constraint.single.is_preferred_identifier = true
438
438
  end
439
439
  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
- debug :instance, "Making #{player.class.basename} #{player.name} using #{l.inspect}" do
56
+ trace :instance, "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
@@ -84,13 +84,15 @@ module ActiveFacts
84
84
  # Find the roles of this clause that do not yet have an instance
85
85
  bare_roles = clause.refs.
86
86
  select do |ref|
87
- next false if ref.binding.instance
88
- next false if ref.literal and
87
+ if !ref.binding.instance and ref.literal
89
88
  ref.binding.instance = instance_identified_by_literal(ref.binding.player, ref.literal)
89
+ end
90
+
91
+ next false if ref.binding.instance
90
92
  true
91
93
  end
92
94
 
93
- debug :instance, "Considering '#{clause.display}' with "+
95
+ trace :instance, "Considering '#{clause.display}' with "+
94
96
  (bare_roles.empty? ? "no bare roles" : "bare roles: #{bare_roles.map{|ref| ref.player.name}*", "}") do
95
97
 
96
98
  # If all the roles are in place, we can bind the rest of this clause:
@@ -107,7 +109,7 @@ module ActiveFacts
107
109
  end
108
110
 
109
111
  return true if progress
110
- debug :instance, "Can't make progress on '#{clause.display}'"
112
+ trace :instance, "Can't make progress on '#{clause.display}'"
111
113
  nil
112
114
  end
113
115
  end
@@ -118,14 +120,14 @@ module ActiveFacts
118
120
  @pass += 1
119
121
 
120
122
  progress = false
121
- debug :instance, "Pass #{@pass} with #{@unbound_clauses.size} clauses to consider" do
123
+ trace :instance, "Pass #{@pass} with #{@unbound_clauses.size} clauses to consider" do
122
124
  @unbound_clauses =
123
125
  @unbound_clauses.select do |clause|
124
126
  action = bind_clause(clause)
125
127
  progress = true if action
126
128
  !action
127
129
  end
128
- debug :instance, "end of pass, unbound clauses are #{@unbound_clauses.map(&:display)*', '}"
130
+ trace :instance, "end of pass, unbound clauses are #{@unbound_clauses.map(&:display)*', '}"
129
131
  end # debug
130
132
  progress
131
133
  end
@@ -139,35 +141,39 @@ module ActiveFacts
139
141
 
140
142
  def bind_complete_fact clause
141
143
  return true unless clause.fact_type # An bare objectification
142
- debug :instance, "All bindings in '#{clause.display}' contain instances; create the fact type"
143
- instances = clause.refs.map{|vr| vr.binding.instance}
144
- debug :instance, "Instances are #{instances.map{|i| "#{i.object_type.name} #{i.value.inspect}"}*", "}"
144
+ trace :instance, "All bindings in '#{clause.display}' contain instances; assert the fact type"
145
+ instances = clause.refs.map{|vr| vr.binding.instance }
146
+ trace :instance, "Instances are #{instances.map{|i| "#{i.verbalise}"}*", "}"
145
147
 
146
148
  if e = clause.fact_type.entity_type and
147
149
  clause.refs[0].binding.instance.object_type == e
148
150
  fact = clause.refs[0].binding.instance.fact
149
151
  else
150
152
  # Check that this fact doesn't already exist
153
+ trace :instance, "Searching for existing fact instance"
154
+
151
155
  fact = clause.fact_type.all_fact.detect do |f|
156
+
152
157
  # Get the role values of this fact in the order of the clause we just bound
153
158
  role_values_in_clause_order = f.all_role_value.sort_by do |rv|
154
159
  clause.reading.role_sequence.all_role_ref.detect{|rr| rr.role == rv.role}.ordinal
155
160
  end
161
+
156
162
  # If all this fact's role values are played by the bound instances, it's the same fact
157
163
  !role_values_in_clause_order.zip(instances).detect{|rv, i| rv.instance != i }
158
164
  end
159
165
  end
160
166
  if fact
161
167
  clause.fact = fact
162
- debug :instance, "Found existing fact type instance"
168
+ trace :instance, "Found existing fact"
163
169
  else
170
+ trace :instance, "Creating new fact of type #{clause.fact_type.default_reading}"
164
171
  fact =
165
172
  clause.fact =
166
173
  @constellation.Fact(:new, :fact_type => clause.fact_type, :population => @population)
167
174
  @bound_facts << fact
168
-
169
175
  clause.reading.role_sequence.all_role_ref_in_order.zip(instances).each do |rr, instance|
170
- debug :instance, "New fact has #{instance.object_type.name} role #{instance.value.inspect}"
176
+ trace :instance, "Assigning fact role #{instance.object_type.name} to #{instance.value ? instance.value.inspect : instance.verbalise}"
171
177
  # REVISIT: Any residual adjectives after the fact type matching are lost here.
172
178
  @constellation.RoleValue(:fact => fact, :instance => instance, :role => rr.role, :population => @population)
173
179
  end
@@ -176,7 +182,7 @@ module ActiveFacts
176
182
  if !fact.instance && clause.fact_type.entity_type
177
183
  # Objectified fact type; create the instance
178
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
179
- debug :instance, "Objectifying fact as #{clause.fact_type.entity_type.name}"
185
+ trace :instance, "Objectifying fact as #{clause.fact_type.entity_type.name}"
180
186
  instance =
181
187
  @constellation.Instance(:new, :object_type => clause.fact_type.entity_type, :fact => fact, :population => @population)
182
188
  @bound_facts << instance
@@ -202,14 +208,14 @@ module ActiveFacts
202
208
  identifying_instance = identifying_binding.instance
203
209
  preferred_identifier = entity_type.preferred_identifier
204
210
 
205
- debug :instance, "This clause associates a new #{binding.player.name} with a #{identifying_binding.player.name}#{identifying_instance ? " which exists" : ""}"
211
+ trace :instance, "This clause associates a new #{binding.player.name} with a #{identifying_binding.player.name}#{identifying_instance ? " which exists" : ""}"
206
212
 
207
213
  identifying_role_ref = preferred_identifier.role_sequence.all_role_ref.detect { |rr|
208
214
  rr.role.fact_type == clause.fact_type && rr.role.object_type == identifying_binding.player
209
215
  }
210
216
  unless identifying_role_ref
211
217
  # This shold never happen; we already bound all refs
212
- debug :instance, "Failed to find a #{identifying_instance.object_type.name}"
218
+ trace :instance, "Failed to find a #{identifying_instance.object_type.name}"
213
219
  return false # We can't do this yet
214
220
  end
215
221
  role_value = identifying_instance.all_role_value.detect do |rv|
@@ -217,7 +223,7 @@ module ActiveFacts
217
223
  end
218
224
  if role_value
219
225
  instance = (role_value.fact.all_role_value.to_a-[role_value])[0].instance
220
- debug :instance, "Found an existing instance (of #{instance.object_type.name}) from a previous definition"
226
+ trace :instance, "Found an existing instance (of #{instance.object_type.name}) from a previous definition"
221
227
  binding.instance = instance
222
228
  return true # Done with this clause
223
229
  end
@@ -240,16 +246,17 @@ module ActiveFacts
240
246
  [rr, identifying_clause, identifying_binding, identifying_instance]
241
247
  end
242
248
  if identifiers.detect{ |i| !i[3] } # Not all required facts are bound yet
243
- debug :instance, "Can't go through with creating #{binding.player.name}; not all the identifying facts are in"
249
+ trace :instance, "Can't go through with creating #{binding.player.name}; not all the identifying facts are in"
244
250
  return false
245
251
  end
246
252
 
247
- debug :instance, "Going ahead with creating #{binding.player.name} using #{identifiers.size} roles" do
253
+ trace :instance, "Creating Entity #{binding.player.name} using #{identifiers.size} roles" do
248
254
  instance = @constellation.Instance(:new, :object_type => entity_type, :population => @population)
249
255
  binding.instance = instance
250
256
  @bound_facts << instance
251
257
  identifiers.each do |rr, identifying_clause, identifying_binding, identifying_instance|
252
258
  # This clause provides the identifying literal for the entity_type
259
+ trace :instance, "Creating existential fact #{rr.role.fact_type.default_reading} for value #{identifying_instance.value.inspect}"
253
260
  id_fact =
254
261
  identifying_clause.fact =
255
262
  @constellation.Fact(:new, :fact_type => rr.role.fact_type, :population => @population)
@@ -267,21 +274,25 @@ module ActiveFacts
267
274
  if object_type.is_a?(ActiveFacts::Metamodel::EntityType)
268
275
  entity_identified_by_literal object_type, literal
269
276
  else
270
- debug :instance, "Making ValueType #{object_type.name} #{literal.inspect} #{@population.name.size>0 ? " in "+@population.name.inspect : ''}" do
271
-
277
+ trace :instance, "Assert Value #{object_type.name} #{literal.inspect}" do
272
278
  is_literal_string = literal.literal.is_a?(String)
273
- instance = @constellation.Instance.detect do |key, i|
279
+ # REVISIT: Check for subtypes and supertypes also, and promote type if necessary
280
+ instance = object_type.all_instance.detect do |i|
281
+ #instance = @constellation.Instance.detect do |key, i|
274
282
  # REVISIT: And same unit
283
+ trace :instance, "Comparing #{i.value.literal.inspect} to #{literal.literal.inspect}"
275
284
  i.population == @population &&
276
285
  i.value &&
277
- i.value.literal == literal &&
286
+ i.value.literal.inspect == literal.literal.inspect &&
278
287
  i.value.is_literal_string == is_literal_string
279
288
  end
280
289
  #instance = object_type.all_instance.detect { |instance|
281
290
  # instance.population == @population && instance.value == literal
282
291
  #}
283
- debug :instance, "This #{object_type.name} value already exists" if instance
284
- unless instance
292
+ if instance
293
+ trace :instance, "This #{object_type.name} value already exists"
294
+ else
295
+ trace :instance, "Creating Value #{object_type.name} #{literal.inspect} #{@population.name.size>0 ? " in "+@population.name.inspect : ''}"
285
296
  instance = @constellation.Instance(:new)
286
297
  instance.object_type = object_type
287
298
  instance.population = @population
@@ -296,7 +307,7 @@ module ActiveFacts
296
307
  def entity_identified_by_literal object_type, literal
297
308
  # A literal that identifies an entity type means the entity type has only one identifying role
298
309
  # That role is played either by a value type, or by another similarly single-identified entity type
299
- debug "Making EntityType #{object_type.name} identified by '#{literal}' #{@population.name.size>0 ? " in "+@population.name.inspect : ''}" do
310
+ trace :instance, "Assert Entity #{object_type.name} identified by '#{literal}'" do
300
311
  identifying_role_refs = object_type.preferred_identifier.role_sequence.all_role_ref
301
312
  raise "Single literal cannot satisfy multiple identifying roles for #{object_type.name}" if identifying_role_refs.size > 1
302
313
  role = identifying_role_refs.single.role
@@ -312,13 +323,15 @@ module ActiveFacts
312
323
  }
313
324
  if instance_rv
314
325
  instance = existing_instance
315
- debug :instance, "This #{object_type.name} entity already exists"
326
+ trace :instance, "This #{object_type.name} entity already exists"
316
327
  else
317
328
  # This fact has no clause.
329
+ trace :instance, "Creating implicit existential fact #{role.fact_type.default_reading}"
318
330
  fact = @constellation.Fact(:new, :fact_type => role.fact_type, :population => @population)
319
331
  @bound_facts << fact
320
332
  # This instance will be associated with its binding by our caller
321
333
  instance = @constellation.Instance(:new, :object_type => object_type, :population => @population)
334
+ trace :instance, "Creating Entity #{object_type.name} identified by '#{literal}' #{@population.name.size>0 ? " in "+@population.name.inspect : ''}"
322
335
  @bound_facts << instance
323
336
  # The identifying fact type has two roles; create both role instances:
324
337
  @constellation.RoleValue(:instance => identifying_instance, :fact => fact, :population => @population, :role => role)