activefacts 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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)