activefacts 0.8.16 → 0.8.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (100) hide show
  1. checksums.yaml +15 -0
  2. data/Manifest.txt +10 -4
  3. data/bin/afgen +26 -20
  4. data/bin/cql +1 -1
  5. data/css/orm2.css +89 -9
  6. data/examples/CQL/CompanyDirectorEmployee.cql +4 -4
  7. data/examples/CQL/Genealogy.cql +5 -5
  8. data/examples/CQL/Metamodel.cql +121 -91
  9. data/examples/CQL/MonthInSeason.cql +2 -6
  10. data/examples/CQL/SeparateSubtype.cql +11 -9
  11. data/examples/CQL/ServiceDirector.cql +21 -33
  12. data/examples/CQL/Supervision.cql +0 -3
  13. data/examples/CQL/WindowInRoomInBldg.cql +10 -4
  14. data/examples/CQL/unit.cql +1 -1
  15. data/lib/activefacts.rb +1 -0
  16. data/lib/activefacts/cql/CQLParser.treetop +5 -1
  17. data/lib/activefacts/cql/Context.treetop +2 -7
  18. data/lib/activefacts/cql/Expressions.treetop +2 -2
  19. data/lib/activefacts/cql/FactTypes.treetop +37 -31
  20. data/lib/activefacts/cql/Language/English.treetop +21 -4
  21. data/lib/activefacts/cql/LexicalRules.treetop +59 -1
  22. data/lib/activefacts/cql/ObjectTypes.treetop +22 -12
  23. data/lib/activefacts/cql/Terms.treetop +13 -9
  24. data/lib/activefacts/cql/ValueTypes.treetop +30 -11
  25. data/lib/activefacts/cql/compiler.rb +34 -5
  26. data/lib/activefacts/cql/compiler/clause.rb +207 -116
  27. data/lib/activefacts/cql/compiler/constraint.rb +129 -105
  28. data/lib/activefacts/cql/compiler/entity_type.rb +49 -27
  29. data/lib/activefacts/cql/compiler/expression.rb +71 -42
  30. data/lib/activefacts/cql/compiler/fact.rb +70 -64
  31. data/lib/activefacts/cql/compiler/fact_type.rb +108 -57
  32. data/lib/activefacts/cql/compiler/query.rb +178 -0
  33. data/lib/activefacts/cql/compiler/shared.rb +13 -12
  34. data/lib/activefacts/cql/compiler/value_type.rb +10 -4
  35. data/lib/activefacts/cql/nodes.rb +1 -1
  36. data/lib/activefacts/cql/parser.rb +6 -2
  37. data/lib/activefacts/generate/absorption.rb +6 -3
  38. data/lib/activefacts/generate/cql.rb +140 -84
  39. data/lib/activefacts/generate/dm.rb +12 -6
  40. data/lib/activefacts/generate/help.rb +25 -6
  41. data/lib/activefacts/generate/helpers/oo.rb +195 -0
  42. data/lib/activefacts/generate/helpers/ordered.rb +589 -0
  43. data/lib/activefacts/generate/helpers/rails.rb +57 -0
  44. data/lib/activefacts/generate/html/glossary.rb +274 -54
  45. data/lib/activefacts/generate/json.rb +25 -22
  46. data/lib/activefacts/generate/null.rb +1 -0
  47. data/lib/activefacts/generate/rails/models.rb +244 -0
  48. data/lib/activefacts/generate/rails/schema.rb +185 -0
  49. data/lib/activefacts/generate/records.rb +1 -0
  50. data/lib/activefacts/generate/ruby.rb +51 -30
  51. data/lib/activefacts/generate/sql/mysql.rb +5 -3
  52. data/lib/activefacts/generate/sql/server.rb +8 -4
  53. data/lib/activefacts/generate/text.rb +1 -0
  54. data/lib/activefacts/generate/transform/surrogate.rb +209 -0
  55. data/lib/activefacts/generate/version.rb +1 -0
  56. data/lib/activefacts/input/orm.rb +234 -181
  57. data/lib/activefacts/mapping/rails.rb +122 -0
  58. data/lib/activefacts/persistence/columns.rb +34 -18
  59. data/lib/activefacts/persistence/foreignkey.rb +129 -71
  60. data/lib/activefacts/persistence/index.rb +42 -12
  61. data/lib/activefacts/persistence/reference.rb +37 -23
  62. data/lib/activefacts/persistence/tables.rb +53 -19
  63. data/lib/activefacts/registry.rb +11 -0
  64. data/lib/activefacts/support.rb +28 -10
  65. data/lib/activefacts/version.rb +1 -1
  66. data/lib/activefacts/vocabulary/extensions.rb +246 -117
  67. data/lib/activefacts/vocabulary/metamodel.rb +105 -65
  68. data/lib/activefacts/vocabulary/verbaliser.rb +226 -194
  69. data/spec/absorption_spec.rb +1 -0
  70. data/spec/cql/comparison_spec.rb +8 -8
  71. data/spec/cql/contractions_spec.rb +16 -43
  72. data/spec/cql/entity_type_spec.rb +2 -1
  73. data/spec/cql/expressions_spec.rb +2 -2
  74. data/spec/cql/fact_type_matching_spec.rb +4 -1
  75. data/spec/cql/parser/bad_literals_spec.rb +30 -30
  76. data/spec/cql/parser/entity_types_spec.rb +6 -6
  77. data/spec/cql/parser/expressions_spec.rb +25 -19
  78. data/spec/cql/samples_spec.rb +5 -4
  79. data/spec/cql_cql_spec.rb +2 -1
  80. data/spec/cql_dm_spec.rb +4 -0
  81. data/spec/cql_mysql_spec.rb +4 -0
  82. data/spec/cql_parse_spec.rb +2 -0
  83. data/spec/cql_ruby_spec.rb +4 -0
  84. data/spec/cql_sql_spec.rb +4 -0
  85. data/spec/cqldump_spec.rb +7 -4
  86. data/spec/helpers/parse_to_ast_matcher.rb +7 -3
  87. data/spec/helpers/test_parser.rb +2 -0
  88. data/spec/norma_cql_spec.rb +5 -2
  89. data/spec/norma_ruby_spec.rb +4 -1
  90. data/spec/norma_ruby_sql_spec.rb +4 -1
  91. data/spec/norma_sql_spec.rb +4 -1
  92. data/spec/norma_tables_spec.rb +2 -2
  93. data/spec/ruby_api_spec.rb +1 -1
  94. data/spec/spec_helper.rb +2 -0
  95. data/spec/transform_surrogate_spec.rb +59 -0
  96. metadata +70 -60
  97. data/TODO +0 -308
  98. data/lib/activefacts/cql/compiler/join.rb +0 -162
  99. data/lib/activefacts/generate/oo.rb +0 -176
  100. data/lib/activefacts/generate/ordered.rb +0 -602
@@ -23,3 +23,4 @@ module ActiveFacts
23
23
  end
24
24
  end
25
25
 
26
+ ActiveFacts::Registry.generator('version', ActiveFacts::Generate::VERSION)
@@ -144,28 +144,35 @@ module ActiveFacts
144
144
  read_diagrams if @options.include?("diagrams")
145
145
  end
146
146
 
147
+ def id_of(x)
148
+ x['id'][1..-1]
149
+ end
150
+
147
151
  def read_entity_types
148
152
  # get and process all the entity types:
149
153
  entity_types = []
150
154
  x_entity_types = @x_model.xpath("orm:Objects/orm:EntityType")
151
- x_entity_types.each{|x|
155
+ x_entity_types.each do |x|
152
156
  id = x['id']
153
157
  name = (x['Name'] || "").gsub(/\s+/,' ').gsub(/-/,'_').strip
154
158
  name = nil if name.size == 0
155
- entity_types <<
156
- @by_id[id] =
157
- entity_type =
158
- @constellation.EntityType(@vocabulary, name, :guid => :new)
159
- independent = x['IsIndependent']
160
- entity_type.is_independent = true if independent && independent == 'true'
161
- personal = x['IsPersonal']
162
- entity_type.pronoun = 'personal' if personal && personal == 'true'
159
+ entity_type =
160
+ @by_id[id] =
161
+ debug :orm, "Asserting new EntityType #{name.inspect}" do
162
+ @vocabulary.valid_entity_type_name(name) ||
163
+ @constellation.EntityType(@vocabulary, name, :guid => id_of(x))
164
+ end
165
+ entity_types << entity_type
166
+ independent = x['IsIndependent']
167
+ entity_type.is_independent = true if independent && independent == 'true'
168
+ personal = x['IsPersonal']
169
+ entity_type.pronoun = 'personal' if personal && personal == 'true'
163
170
  # x_pref = x.xpath("orm:PreferredIdentifier")[0]
164
171
  # if x_pref
165
172
  # pi_id = x_pref['ref']
166
173
  # @pref_id_for[pi_id] = x
167
174
  # end
168
- }
175
+ end
169
176
  end
170
177
 
171
178
  def read_value_types
@@ -198,7 +205,14 @@ module ActiveFacts
198
205
  type_name.sub!(/^orm:/,'')
199
206
 
200
207
  type_name.sub!(/DataType\Z/,'')
201
- type_name = DataTypeMapping[type_name] || type_name
208
+ if t = DataTypeMapping[type_name]
209
+ existing = @constellation.ObjectType[[@vocabulary.identifying_role_values, t]]
210
+ if !existing || existing.is_a?(ActiveFacts::Metamodel::ValueType)
211
+ # There's no type conflict, so use the mapped name.
212
+ type_name = t
213
+ end
214
+ end
215
+ debug :orm, "Using #{type_name.inspect} as supertype for new #{name}"
202
216
  if !length and type_name =~ /\(([0-9]+)\)/
203
217
  length = $1.to_i
204
218
  end
@@ -216,14 +230,30 @@ module ActiveFacts
216
230
  supertype_name = x_supertype['Name']
217
231
  raise "Supertype of #{name} is post-defined but recursiving processing failed" unless supertype
218
232
  raise "Supertype #{supertype_name} of #{name} is not a value type" unless supertype.kind_of? ActiveFacts::Metamodel::ValueType
219
- value_super_type = @constellation.ValueType(@vocabulary, supertype_name, :guid => :new)
233
+ debug :orm, "Asserting new ValueType #{supertype_name.inspect} for supertype" do
234
+ value_super_type =
235
+ @vocabulary.valid_value_type_name(supertype_name) ||
236
+ @constellation.ValueType(@vocabulary, supertype_name, :guid => id_of(x_supertype))
237
+ end
220
238
  else
221
239
  # REVISIT: Need to handle standard types better here:
222
- value_super_type = type_name != name ? @constellation.ValueType(@vocabulary, type_name, :guid => :new) : nil
240
+ value_super_type =
241
+ if type_name != name
242
+ debug :orm, "Asserting new ValueType #{type_name.inspect} for supertype" do
243
+ @vocabulary.valid_value_type_name(type_name) ||
244
+ @constellation.ValueType(@vocabulary.identifying_role_values, type_name, :guid => :new)
245
+ end
246
+ else
247
+ nil
248
+ end
223
249
  end
224
250
 
225
- @by_id[id] =
226
- vt = @constellation.ValueType(@vocabulary, name, :guid => :new)
251
+ vt =
252
+ debug :orm, "Asserting new ValueType #{name.inspect}" do
253
+ @by_id[id] =
254
+ @vocabulary.valid_value_type_name(name) ||
255
+ @constellation.ValueType(@vocabulary.identifying_role_values, name, :guid => id_of(x))
256
+ end
227
257
  vt.supertype = value_super_type
228
258
  vt.length = length if length
229
259
  vt.scale = scale if scale && scale != 0
@@ -236,7 +266,7 @@ module ActiveFacts
236
266
  x_vr.each{|vr|
237
267
  x_ranges = vr.xpath("orm:ValueRanges/orm:ValueRange")
238
268
  next if x_ranges.size == 0
239
- vt.value_constraint = @by_id[vr['id']] = @constellation.ValueConstraint(:new)
269
+ vt.value_constraint = @by_id[vr['id']] = @constellation.ValueConstraint(id_of(vr))
240
270
  x_ranges.each{|x_range|
241
271
  v_range = value_range(x_range)
242
272
  ar = @constellation.AllowedRange(vt.value_constraint, v_range)
@@ -245,16 +275,23 @@ module ActiveFacts
245
275
  vt
246
276
  end
247
277
 
278
+ def assert_value(val, string)
279
+ if val
280
+ @constellation.Value(val.to_s, string, nil)
281
+ else
282
+ nil
283
+ end
284
+ end
285
+
248
286
  def value_range(x_range)
249
287
  min = x_range['MinValue']
250
288
  max = x_range['MaxValue']
251
289
 
252
- strings = is_a_string(min) || is_a_string(max)
290
+ strings = is_literal_string(min) || is_literal_string(max)
253
291
  # ValueRange takes a minimum and/or a maximum Bound, each takes value and whether inclusive
254
- @constellation.ValueRange(
255
- min && min != '' ? [[min, strings, nil], true] : nil,
256
- max && max != '' ? [[max, strings, nil], true] : nil
257
- )
292
+ @constellation.ValueRange(
293
+ min.length > 0 ? @constellation.Bound(assert_value(min, strings), true) : nil,
294
+ max.length > 0 ? @constellation.Bound(assert_value(max, strings), true) : nil)
258
295
  end
259
296
 
260
297
  def read_fact_types
@@ -271,7 +308,7 @@ module ActiveFacts
271
308
  next if x.xpath("orm:DerivationRule").size > 0
272
309
 
273
310
  debug :orm, "FactType #{name || id}"
274
- facts << @by_id[id] = fact_type = @constellation.FactType(:new)
311
+ facts << @by_id[id] = fact_type = @constellation.FactType(id_of(x))
275
312
  }
276
313
  end
277
314
  end
@@ -316,7 +353,7 @@ module ActiveFacts
316
353
  next if subtype.kind_of? ActiveFacts::Metamodel::ValueType or
317
354
  supertype.kind_of? ActiveFacts::Metamodel::ValueType
318
355
 
319
- inheritance_fact = @constellation.TypeInheritance(subtype, supertype, :guid => :new)
356
+ inheritance_fact = @constellation.TypeInheritance(subtype, supertype, :guid => id_of(x))
320
357
  if x["IsPrimary"] == "true" or # Old way
321
358
  x["PreferredIdentificationPath"] == "true" # Newer
322
359
  debug :orm, "#{supertype.name} is primary supertype of #{subtype.name}"
@@ -328,22 +365,22 @@ module ActiveFacts
328
365
  facts << @by_id[id] = inheritance_fact
329
366
 
330
367
  # Create the new Roles so we can find constraints on them:
331
- subtype_role = @by_id[subtype_role_id] = @constellation.Role(inheritance_fact, 0, :object_type => subtype, :guid => :new)
332
- supertype_role = @by_id[supertype_role_id] = @constellation.Role(inheritance_fact, 1, :object_type => supertype, :guid => :new)
368
+ subtype_role = @by_id[subtype_role_id] = @constellation.Role(inheritance_fact, 0, :object_type => subtype, :guid => id_of(x_subtype_role))
369
+ supertype_role = @by_id[supertype_role_id] = @constellation.Role(inheritance_fact, 1, :object_type => supertype, :guid => id_of(x_supertype_role))
333
370
 
334
371
  # Create readings, so constraints can be verbalised for example:
335
372
  rs = @constellation.RoleSequence(:new)
336
373
  @constellation.RoleRef(rs, 0, :role => subtype_role)
337
374
  @constellation.RoleRef(rs, 1, :role => supertype_role)
338
- @constellation.Reading(inheritance_fact, 0, :role_sequence => rs, :text => "{0} is a kind of {1}")
339
- @constellation.Reading(inheritance_fact, 1, :role_sequence => rs, :text => "{0} is a subtype of {1}")
375
+ @constellation.Reading(inheritance_fact, 0, :role_sequence => rs, :text => "{0} is a kind of {1}", :is_negative => false)
376
+ @constellation.Reading(inheritance_fact, 1, :role_sequence => rs, :text => "{0} is a subtype of {1}", :is_negative => false)
340
377
 
341
378
  rs2 = @constellation.RoleSequence(:new)
342
379
  @constellation.RoleRef(rs2, 0, :role => supertype_role)
343
380
  @constellation.RoleRef(rs2, 1, :role => subtype_role)
344
381
  n = 'aeiouh'.include?(subtype_role.object_type.name.downcase[0]) ? 1 : 0
345
- @constellation.Reading(inheritance_fact, 2+n, :role_sequence => rs2, :text => "{0} is a {1}")
346
- @constellation.Reading(inheritance_fact, 3-n, :role_sequence => rs2, :text => "{0} is an {1}")
382
+ @constellation.Reading(inheritance_fact, 2+n, :role_sequence => rs2, :text => "{0} is a {1}", :is_negative => false)
383
+ @constellation.Reading(inheritance_fact, 3-n, :role_sequence => rs2, :text => "{0} is an {1}", :is_negative => false)
347
384
  }
348
385
  end
349
386
  end
@@ -366,12 +403,13 @@ module ActiveFacts
366
403
  fact_id = x_fact_type['ref']
367
404
  fact_type = @by_id[fact_id]
368
405
  next if x.xpath("orm:DerivationRule").size > 0
369
- throw "Nested fact #{fact_id} not found" if !fact_type
406
+ next unless fact_type # "Nested fact #{fact_id} not found; objectification of a derived fact type?"
370
407
 
371
408
  debug :orm, "NestedType #{name} is #{id}, nests #{fact_type.guid}"
372
409
  @nested_types <<
373
410
  @by_id[id] =
374
- nested_type = @constellation.EntityType(@vocabulary, name, :guid => :new)
411
+ nested_type = @vocabulary.valid_entity_type_name(name) ||
412
+ @constellation.EntityType(@vocabulary, name, :guid => id_of(x))
375
413
  independent = x['IsIndependent']
376
414
  nested_type.is_independent = true if independent && independent == 'true' && !is_implied
377
415
  nested_type.is_implied_by_objectification = is_implied
@@ -382,8 +420,8 @@ module ActiveFacts
382
420
 
383
421
  def complete_nested_types
384
422
  @nested_types.each do |nested_type|
385
- # Create the phantom roles here. These will be used later when we create objectification joins,
386
- # but for now there's nothing we import from NORMA which requires objectification joins.
423
+ # Create the phantom roles here. These will be used later when we create objectification steps,
424
+ # but for now there's nothing we import from NORMA which requires objectification steps.
387
425
  # Consequently there's no need to index them against NORMA's phantom roles.
388
426
  nested_type.create_implicit_fact_types
389
427
  end
@@ -400,7 +438,6 @@ module ActiveFacts
400
438
  fact_name = nil if fact_name == ''
401
439
 
402
440
  x_fact_roles = x.xpath('orm:FactRoles/*')
403
- x_reading_orders = x.xpath('orm:ReadingOrders/*')
404
441
 
405
442
  # Deal with FactRoles (Roles):
406
443
  debug :orm, "Reading fact roles" do
@@ -438,14 +475,14 @@ module ActiveFacts
438
475
  @by_id.delete(ref) # and de-index it from our list
439
476
  next
440
477
  end
441
- throw "RolePlayer for '#{name}' #{ref} was not found" if !object_type
478
+ throw "RolePlayer for '#{name}' #{ref} in fact type #{x.parent.parent['_Name']} was not found" if !object_type
442
479
 
443
480
  debug :orm, "#{@vocabulary.name}, RoleName=#{x['Name'].inspect} played by object_type=#{object_type.name}"
444
481
  throw "Role is played by #{object_type.class} not ObjectType" if !(@constellation.vocabulary.object_type(:ObjectType) === object_type)
445
482
 
446
483
  debug :orm, "Creating role #{name} nr#{fact_type.all_role.size} of #{fact_type.guid} played by #{object_type.name}"
447
484
 
448
- role = @by_id[id] = @constellation.Role(fact_type, fact_type.all_role.size, :object_type => object_type, :guid => :new)
485
+ role = @by_id[id] = @constellation.Role(fact_type, fact_type.all_role.size, :object_type => object_type, :guid => id_of(x))
449
486
  role.role_name = name if name && name != object_type.name
450
487
  debug :orm, "Fact #{fact_name} (id #{fact_type.guid.object_id}) role #{x['Name']} is played by #{object_type.name}, role is #{role.object_id}"
451
488
 
@@ -453,7 +490,7 @@ module ActiveFacts
453
490
  x_vr.each{|vr|
454
491
  x_ranges = vr.xpath("orm:ValueRanges/orm:ValueRange")
455
492
  next if x_ranges.size == 0
456
- role.role_value_constraint = @by_id[vr['id']] = @constellation.ValueConstraint(:new)
493
+ role.role_value_constraint = @by_id[vr['id']] = @constellation.ValueConstraint(id_of(vr))
457
494
  x_ranges.each{|x_range|
458
495
  v_range = value_range(x_range)
459
496
  ar = @constellation.AllowedRange(role.role_value_constraint, v_range)
@@ -468,6 +505,7 @@ module ActiveFacts
468
505
 
469
506
  # Deal with Readings:
470
507
  debug :orm, "Reading fact readings" do
508
+ x_reading_orders = x.xpath('orm:ReadingOrders/*')
471
509
  x_reading_orders.each{|x|
472
510
  x_role_sequence = x.xpath('orm:RoleSequence/*')
473
511
  x_readings = x.xpath('orm:Readings/orm:Reading/orm:Data')
@@ -483,7 +521,7 @@ module ActiveFacts
483
521
  # }
484
522
 
485
523
  x_readings.each_with_index{|x, i|
486
- reading = @constellation.Reading(fact_type, fact_type.all_reading.size)
524
+ reading = @constellation.Reading(fact_type, fact_type.all_reading.size, :is_negative => false)
487
525
  reading.role_sequence = role_sequence
488
526
  # REVISIT: The downcase here only needs to be the initial letter of each word, but be safe:
489
527
  reading.text = extract_adjectives(x.text, role_sequence)
@@ -672,18 +710,18 @@ module ActiveFacts
672
710
  #puts "Residual Mandatory #{name}: #{role_sequence.to_s}"
673
711
 
674
712
  if (players = role_sequence.all_role_ref.map{|rr| rr.role.object_type}).uniq.size > 1
675
- join_over, = *ActiveFacts::Metamodel.join_roles_over(role_sequence.all_role_ref.map{|rr| rr.role}, :proximate)
713
+ join_over, = *ActiveFacts::Metamodel.plays_over(role_sequence.all_role_ref.map{|rr| rr.role}, :proximate)
676
714
  raise "Mandatory join constraint #{name} has incompatible players #{players.map{|o| o.name}.inspect}" unless join_over
677
715
  if players.detect{|p| p != join_over}
678
- debug :join, "subtyping join simple mandatory constraint #{name} over #{join_over.name}"
716
+ debug :query, "subtyping step simple mandatory constraint #{name} over #{join_over.name}"
679
717
  players.each_with_index do |player, i|
680
718
  next if player != join_over
681
- # REVISIT: We don't need to make a subtyping join here (from join_over to player)
719
+ # REVISIT: We don't need to make a subtyping step here (from join_over to player)
682
720
  end
683
721
  end
684
722
  end
685
723
 
686
- pc = @constellation.PresenceConstraint(:new)
724
+ pc = @constellation.PresenceConstraint(id_of(x))
687
725
  pc.vocabulary = @vocabulary
688
726
  pc.name = name
689
727
  pc.role_sequence = role_sequence
@@ -718,15 +756,21 @@ module ActiveFacts
718
756
  next if !role_sequence
719
757
  #puts "uc: #{role_sequence.all_role_ref.map{|rr|rr.role.fact_type.default_reading}*', '}"
720
758
 
721
- # Check for a join
759
+ # Check for a query
722
760
  if (fact_types = role_sequence.all_role_ref.map{|rr| rr.role.fact_type}).uniq.size > 1
723
- join_over, = *ActiveFacts::Metamodel.join_roles_over(role_sequence.all_role_ref.map{|rr| rr.role}, :counterpart)
761
+ join_over, = *ActiveFacts::Metamodel.plays_over(role_sequence.all_role_ref.map{|rr| rr.role}, :counterpart)
724
762
 
725
763
  players = role_sequence.all_role_ref.map{|rr| rr.role.object_type.name}.uniq
726
- raise "Uniqueness join constraint #{name} has incompatible players #{players.inspect}" unless join_over
764
+ unless join_over
765
+ if x.xpath("orm:RoleSequence/orm:JoinRule").size > 0
766
+ $stderr.puts "Ignoring Join #{name} because its query is not understood"
767
+ next
768
+ end
769
+ raise "Uniqueness join constraint #{name} has incompatible players #{players.inspect}"
770
+ end
727
771
  subtyping = players.size > 1 ? 'subtyping ' : ''
728
- # REVISIT: Create the Join, the JoinNode for join_over, and steps from each role_ref to join_over
729
- debug :join, "#{subtyping}join uniqueness constraint over #{join_over.name} in #{fact_types.map(&:default_reading)*', '}"
772
+ # REVISIT: Create the Query, the Variable for join_over, and steps from each role_ref to join_over
773
+ debug :query, "#{subtyping}join uniqueness constraint over #{join_over.name} in #{fact_types.map(&:default_reading)*', '}"
730
774
  end
731
775
 
732
776
  # There is an implicit uniqueness constraint when any object plays a unary. Skip it.
@@ -769,7 +813,7 @@ module ActiveFacts
769
813
  role.object_type == fact_type.supertype &&
770
814
  fact_type.provides_identification
771
815
 
772
- pc = @constellation.PresenceConstraint(:new)
816
+ pc = @constellation.PresenceConstraint(id_of(x))
773
817
  pc.vocabulary = @vocabulary
774
818
  pc.name = name
775
819
  pc.role_sequence = role_sequence
@@ -788,23 +832,23 @@ module ActiveFacts
788
832
  end
789
833
  end
790
834
 
791
- def subtype_join_step(join, ti)
792
- subtype_node = join.all_join_node.detect{|jn| jn.object_type == ti.subtype } ||
793
- @constellation.JoinNode(join, join.all_join_node.size, :object_type => ti.subtype)
794
- supertype_node = join.all_join_node.detect{|jn| jn.object_type == ti.supertype } ||
795
- @constellation.JoinNode(join, join.all_join_node.size, :object_type => ti.supertype)
835
+ def subtype_step(query, ti)
836
+ subtype_node = query.all_variable.detect{|jn| jn.object_type == ti.subtype } ||
837
+ @constellation.Variable(query, query.all_variable.size, :object_type => ti.subtype)
838
+ supertype_node = query.all_variable.detect{|jn| jn.object_type == ti.supertype } ||
839
+ @constellation.Variable(query, query.all_variable.size, :object_type => ti.supertype)
796
840
  rs = @constellation.RoleSequence(:new)
797
841
  @constellation.RoleRef(rs, 0, :role => ti.subtype_role)
798
- sub_jr = @constellation.JoinRole(subtype_node, ti.subtype_role)
842
+ sub_play = @constellation.Play(subtype_node, ti.subtype_role)
799
843
  @constellation.RoleRef(rs, 1, :role => ti.supertype_role)
800
- sup_jr = @constellation.JoinRole(supertype_node, ti.supertype_role)
801
- js = @constellation.JoinStep(sub_jr, sup_jr, :fact_type => ti)
802
- debug :join, "New subtyping join step #{js.describe}"
803
- js
844
+ sup_play = @constellation.Play(supertype_node, ti.supertype_role)
845
+ step = @constellation.Step(sub_play, sup_play, :fact_type => ti)
846
+ debug :query, "New subtyping step #{step.describe}"
847
+ step
804
848
  end
805
849
 
806
- # Make as many join steps as it takes to get from subtype to supertype
807
- def subtype_join_steps(join, subtype, supertype)
850
+ # Make as many steps as it takes to get from subtype to supertype
851
+ def subtype_steps(query, subtype, supertype)
808
852
  primary_ti = nil
809
853
  other_ti = nil
810
854
  subtype.all_type_inheritance_as_subtype.each do |ti|
@@ -816,24 +860,24 @@ module ActiveFacts
816
860
  end
817
861
  end
818
862
  ti = primary_ti || other_ti
819
- # Make supertype join steps first:
820
- (ti.supertype == supertype ? [] : subtype_join_steps(join, ti.supertype, supertype)) +
821
- [subtype_join_step(join, ti)]
863
+ # Make supertype steps first:
864
+ (ti.supertype == supertype ? [] : subtype_steps(query, ti.supertype, supertype)) +
865
+ [subtype_step(query, ti)]
822
866
  end
823
867
 
824
- # Equality and subset joins involve two or more role sequences,
868
+ # Equality and subset join constraints involve two or more role sequences,
825
869
  # and the respective roles from each sequence must be compatible,
826
- # Compatibility might involve subtyping joins but not objectification joins
870
+ # Compatibility might involve subtyping steps but not objectification steps
827
871
  # to the respective end-point (constrained object type).
828
872
  # Also, all roles in each sequence constitute a join over a single
829
- # object type, which might involve subtyping or objectification joins.
873
+ # object type, which might involve subtyping or objectification steps.
830
874
  #
831
- def make_joins(constraint_type, name, role_sequences)
875
+ def make_queries(constraint_type, name, role_sequences)
832
876
  begin
833
877
  # Get the object types constrained for each position in the role sequences.
834
- # Supertyping joins may be needed to reach them.
878
+ # Supertyping steps may be needed to reach them.
835
879
  end_points = [] # An array of the common supertype for matching role_refs across the sequences
836
- end_joins = [] # An array of booleans indicating whether any role_sequence requires a subtyping join
880
+ end_steps = [] # An array of booleans indicating whether any role_sequence requires subtyping steps
837
881
  role_sequences[0].all_role_ref.size.times do |i|
838
882
  role_refs = role_sequences.map{|rs| rs.all_role_ref.detect{|rr| rr.ordinal == i}}
839
883
  if (fact_types = role_refs.map{|rr| rr.role.fact_type}).uniq.size == 1
@@ -842,9 +886,9 @@ module ActiveFacts
842
886
  end
843
887
  if (players = role_refs.map{|rr| rr.role.object_type}).uniq.size == 1
844
888
  end_point = players[0]
845
- end_joins[i] = false
889
+ end_steps[i] = false
846
890
  else
847
- # Can the players be joined using a subtyping join?
891
+ # Can the players be joined using subtyping steps?
848
892
  common_supertypes = players[1..-1].
849
893
  inject(players[0].supertypes_transitive) do |remaining, player|
850
894
  remaining & player.supertypes_transitive
@@ -852,33 +896,33 @@ module ActiveFacts
852
896
  end_point = common_supertypes[0]
853
897
 
854
898
  raise "constrained roles of #{constraint_type} #{name} are incompatible (#{players.map(&:name)*', '})" if common_supertypes.size == 0
855
- end_joins[i] = true
899
+ end_steps[i] = true
856
900
  end
857
901
  end_points[i] = end_point
858
902
  end
859
903
 
860
904
  # For each role_sequence, find the object type over which the join is implied (nil if no join)
861
905
  sequence_join_over = []
862
- if role_sequences[0].all_role_ref.size > 1 # There are joins within each sequence.
906
+ if role_sequences[0].all_role_ref.size > 1 # There are queries within each sequence.
863
907
  sequence_join_over = []
864
908
  sequence_joined_roles = []
865
909
  role_sequences.map do |rs|
866
- join_over, joined_roles = *ActiveFacts::Metamodel.join_roles_over(rs.all_role_ref.map{|rr| rr.role})
910
+ join_over, joined_roles = *ActiveFacts::Metamodel.plays_over(rs.all_role_ref.map{|rr| rr.role})
867
911
  sequence_join_over << join_over
868
912
  sequence_joined_roles << joined_roles
869
913
  end
870
914
  end
871
915
 
872
- # If there are no joins, we can drop out here.
873
- if sequence_join_over.compact.empty? && !end_joins.detect{|e| true}
916
+ # If there are no queries, we can drop out here.
917
+ if sequence_join_over.compact.empty? && !end_steps.detect{|e| true}
874
918
  return true
875
919
  end
876
920
 
877
- debug :join, "#{constraint_type} join constraint #{name} over #{role_sequences.map{|rs|rs.describe}*', '}"
921
+ debug :query, "#{constraint_type} join constraint #{name} over #{role_sequences.map{|rs|rs.describe}*', '}"
878
922
 
879
- join = nil
880
- debug :join, "#{constraint_type} join constraint #{name} constrains #{
881
- end_points.zip(end_joins).map{|(p,j)| (p ? p.name : 'NULL')+(j ? ' & subtypes':'')}*', '
923
+ query = nil
924
+ debug :query, "#{constraint_type} join constraint #{name} constrains #{
925
+ end_points.zip(end_steps).map{|(p,j)| (p ? p.name : 'NULL')+(j ? ' & subtypes':'')}*', '
882
926
  }#{
883
927
  if role_sequences[0].all_role_ref.size > 1
884
928
  ", joined over #{
@@ -891,134 +935,136 @@ module ActiveFacts
891
935
  end
892
936
  }" do
893
937
 
894
- # There may be one join per role sequence:
938
+ # There may be one query per role sequence:
895
939
  role_sequences.zip(sequence_join_over||[], sequence_joined_roles||[]).map do |role_sequence, join_over, joined_roles|
896
- # Skip if there's no join here (sequence join nor end-point subset join)
940
+ # Skip if there's no query here (sequence join nor end-point subset join)
897
941
  role_refs = role_sequence.all_role_ref_in_order
898
942
  if !join_over and !role_refs.detect{|rr| rr.role.object_type != end_points[rr.ordinal]}
899
943
  # No sequence join nor end_point join here
900
944
  next
901
945
  end
902
946
 
903
- # A RoleSequence for the actual join end-points
947
+ # A RoleSequence for the actual query end-points
904
948
  replacement_rs = @constellation.RoleSequence(:new)
905
949
 
906
- join = @constellation.Join(:new)
907
- join_node = nil
908
- join_role = nil
950
+ query = @constellation.Query(:new)
951
+ variable = nil
952
+ query_role = nil
909
953
  role_refs.zip(joined_roles||[]).each_with_index do |(role_ref, joined_role), i|
910
954
 
911
- # Each role_ref is to an object joined via joined_role to join_node (or which will be the join_node)
955
+ # Each role_ref is to an object joined via joined_role to variable (or which will be the variable)
912
956
 
913
- # Create a join node for the actual end-point (supertype of the constrained roles)
957
+ # Create a variable for the actual end-point (supertype of the constrained roles)
914
958
  end_point = end_points[i]
915
959
  unless end_point
916
- raise "In #{constraint_type} #{name}, there is a faulty or non-translated join"
960
+ raise "In #{constraint_type} #{name}, there is a faulty or non-translated query"
917
961
  end
918
- debug :join, "Join Node #{join.all_join_node.size} is for #{end_point.name}"
919
- end_node = @constellation.JoinNode(join, join.all_join_node.size, :object_type => end_point)
962
+ debug :query, "Variable #{query.all_variable.size} is for #{end_point.name}"
963
+ end_node = @constellation.Variable(query, query.all_variable.size, :object_type => end_point)
920
964
 
921
965
  # We're going to rewrite the constraint to constrain the supertype roles, but assume they're the same:
922
966
  role_node = end_node
923
967
  end_role = role_ref.role
924
968
 
925
- # Create subtyping join steps at the end-point, if needed:
926
- projecting_jr = nil
927
- constrained_join_role = nil
969
+ # Create subtyping steps at the end-point, if needed:
970
+ projecting_play = nil
971
+ constrained_play = nil
928
972
  if (subtype = role_ref.role.object_type) != end_point
929
- debug :join, "Making subtyping join steps from #{subtype.name} to #{end_point.name}" do
973
+ debug :query, "Making subtyping steps from #{subtype.name} to #{end_point.name}" do
930
974
  # There may be more than one supertyping level. Make the steps:
931
- subtyping_steps = subtype_join_steps(join, subtype, end_point)
932
- js = subtyping_steps[0]
933
- constrained_join_role = subtyping_steps[-1].input_join_role
975
+ subtyping_steps = subtype_steps(query, subtype, end_point)
976
+ step = subtyping_steps[0]
977
+ constrained_play = subtyping_steps[-1].input_play
934
978
 
935
979
  # Replace the constrained role and node with the supertype ones:
936
- end_node = join.all_join_node.detect{|jn| jn.object_type == end_point }
937
- projecting_jr = js.output_join_role
938
- end_role = js.fact_type.all_role.detect{|r| r.object_type == end_point }
939
- role_node = join.all_join_node.detect{|jn| jn.object_type == role_ref.role.object_type }
980
+ end_node = query.all_variable.detect{|jn| jn.object_type == end_point }
981
+ projecting_play = step.output_play
982
+ end_role = step.fact_type.all_role.detect{|r| r.object_type == end_point }
983
+ role_node = query.all_variable.detect{|jn| jn.object_type == role_ref.role.object_type }
940
984
  end
941
985
  end
942
986
 
943
- raise "Internal error in #{constraint_type} #{name}: making illegal reference to join node, end role mismatch" if end_role.object_type != end_node.object_type
987
+ raise "Internal error in #{constraint_type} #{name}: making illegal reference to variable, end role mismatch" if end_role.object_type != end_node.object_type
944
988
  rr = @constellation.RoleRef(replacement_rs, replacement_rs.all_role_ref.size, :role => end_role)
945
- projecting_jr ||= (constrained_join_role = @constellation.JoinRole(end_node, end_role))
946
- projecting_jr.role_ref = rr # Project this RoleRef
989
+ projecting_play ||= (constrained_play = @constellation.Play(end_node, end_role))
990
+ projecting_play.role_ref = rr # Project this RoleRef
991
+ # projecting_play.variable.projection = rr.role # REVISIT: The variable should project a role, not the Play a RoleRef
947
992
 
948
993
  if join_over
949
- if !join_node # Create the JoinNode when processing the first role
950
- debug :join, "Join Node #{join.all_join_node.size} is over #{join_over.name}"
951
- join_node = @constellation.JoinNode(join, join.all_join_node.size, :object_type => join_over)
994
+ if !variable # Create the Variable when processing the first role
995
+ debug :query, "Variable #{query.all_variable.size} is over #{join_over.name}"
996
+ variable = @constellation.Variable(query, query.all_variable.size, :object_type => join_over)
952
997
  end
953
- debug :join, "Making join step from #{end_point.name} to #{join_over.name}" do
998
+ debug :query, "Making step from #{end_point.name} to #{join_over.name}" do
954
999
  rs = @constellation.RoleSequence(:new)
955
- # Detect the fact type over which we're joining (may involve objectification)
956
- raise "Internal error in #{constraint_type} #{name}: making illegal reference to join node, object type mismatch" if role_ref.role.object_type != role_node.object_type
1000
+ # Detect the fact type over which we're stepping (may involve objectification)
1001
+ raise "Internal error in #{constraint_type} #{name}: making illegal reference to variable, object type mismatch" if role_ref.role.object_type != role_node.object_type
957
1002
  @constellation.RoleRef(rs, 0, :role => role_ref.role)
958
- role_jr = @constellation.JoinRole(role_node, role_ref.role)
959
- raise "Internal error in #{constraint_type} #{name}: making illegal reference to join node, joined_role mismatch" if joined_role.object_type != join_node.object_type
1003
+ role_play = @constellation.Play(role_node, role_ref.role)
1004
+ raise "Internal error in #{constraint_type} #{name}: making illegal reference to variable, joined_role mismatch" if joined_role.object_type != variable.object_type
960
1005
  @constellation.RoleRef(rs, 1, :role => joined_role)
961
- join_jr = @constellation.JoinRole(join_node, joined_role)
1006
+ join_play = @constellation.Play(variable, joined_role)
962
1007
 
963
- js = @constellation.JoinStep(role_jr, join_jr, :fact_type => joined_role.fact_type)
964
- debug :join, "New join step #{js.describe}"
1008
+ step = @constellation.Step(role_play, join_play, :fact_type => joined_role.fact_type)
1009
+ debug :query, "New step #{step.describe}"
965
1010
  end
966
1011
  else
967
- debug :join, "Need join step for non-join_over role #{end_point.name} #{role_ref.describe} in #{role_ref.role.fact_type.default_reading}"
1012
+ debug :query, "Need step for non-join_over role #{end_point.name} #{role_ref.describe} in #{role_ref.role.fact_type.default_reading}"
968
1013
  if (roles = role_ref.role.fact_type.all_role.to_a).size > 1
969
1014
  # Here we have an end join (step already created) but no sequence join
970
- if join_node
971
- raise "Internal error in #{constraint_type} #{name}: making illegal join step" if role_ref.role.object_type != role_node.object_type
972
- join_jr = @constellation.JoinRole(join_node, join_role)
973
- role_jr = @constellation.JoinRole(role_node, role_ref.role)
974
- js = @constellation.JoinStep(join_jr, role_jr, :fact_type => role_ref.role.fact_type)
975
- roles -= [join_role, role_ref.role]
1015
+ if variable
1016
+ raise "Internal error in #{constraint_type} #{name}: making illegal step" if role_ref.role.object_type != role_node.object_type
1017
+ join_play = @constellation.Play(variable, query_role)
1018
+ role_play = @constellation.Play(role_node, role_ref.role)
1019
+ step = @constellation.Step(join_play, role_play, :fact_type => role_ref.role.fact_type)
1020
+ roles -= [query_role, role_ref.role]
976
1021
  roles.each do |incidental_role|
977
- jn = @constellation.JoinNode(join, join.all_join_node.size, :object_type => incidental_role.object_type)
978
- jr = @constellation.JoinRole(jn, incidental_role, :join_step => js)
1022
+ jn = @constellation.Variable(query, query.all_variable.size, :object_type => incidental_role.object_type)
1023
+ play = @constellation.Play(jn, incidental_role, :step => step)
979
1024
  end
980
1025
  else
981
1026
  if role_sequence.all_role_ref.size > 1
982
- join_node = role_node
983
- join_role = role_ref.role
1027
+ variable = role_node
1028
+ query_role = role_ref.role
984
1029
  else
985
- # There's no join in this role sequence, so we'd drop of fthe bottom without doing the right things. Why?
1030
+ # There's no query in this role sequence, so we'd drop off the bottom without doing the right things. Why?
986
1031
  # Without this case, Supervision.orm omits "that runs Company" from the exclusion constraint, and I'm not sure why.
987
1032
  # I think the "then" code causes it to drop out the bottom without making the step (which is otherwise made in every case, see CompanyDirectorEmployee for example)
988
- role_jr = @constellation.JoinRole(role_node, role_ref.role)
989
- js = nil
1033
+ role_play = @constellation.Play(role_node, role_ref.role)
1034
+ step = nil
990
1035
  role_ref.role.fact_type.all_role.each do |role|
991
- next if role == role_jr.role
1036
+ next if role == role_play.role
992
1037
  next if role_sequence.all_role_ref.detect{|rr| rr.role == role}
993
- jn = @constellation.JoinNode(join, join.all_join_node.size, :object_type => role.object_type)
994
- jr = @constellation.JoinRole(jn, role)
995
- if js
996
- jr.join_step = js # Incidental role
1038
+ jn = @constellation.Variable(query, query.all_variable.size, :object_type => role.object_type)
1039
+ play = @constellation.Play(jn, role)
1040
+ if step
1041
+ play.step = step # Incidental role
997
1042
  else
998
- js = @constellation.JoinStep(role_jr, jr, :fact_type => role_ref.role.fact_type)
1043
+ step = @constellation.Step(role_play, play, :fact_type => role_ref.role.fact_type)
999
1044
  end
1000
1045
  end
1001
1046
  end
1002
1047
  end
1003
1048
  else
1004
- # Unary fact type, make a Join Step from and to the constrained_join_role
1005
- jr = @constellation.JoinRole(constrained_join_role.join_node, role_ref.role)
1006
- js = @constellation.JoinStep(jr, jr, :fact_type => role_ref.role.fact_type)
1049
+ # Unary fact type, make a Step from and to the constrained_play
1050
+ play = @constellation.Play(constrained_play.variable, role_ref.role)
1051
+ step = @constellation.Step(play, play, :fact_type => role_ref.role.fact_type)
1007
1052
  end
1008
1053
  end
1009
1054
  end
1010
1055
 
1011
- # Thoroughly check that this is a valid join
1012
- join.validate
1013
- debug :join, "Join has projected nodes #{replacement_rs.describe}"
1056
+ # Thoroughly check that this is a valid query
1057
+ query.validate
1058
+ debug :query, "Query has projected nodes #{replacement_rs.describe}"
1014
1059
 
1015
- # Constrain the replacement role sequence, which has the attached join:
1060
+ # Constrain the replacement role sequence, which has the attached query:
1016
1061
  role_sequences[role_sequences.index(role_sequence)] = replacement_rs
1017
1062
  end
1018
1063
  return true
1019
1064
  end
1020
1065
  rescue => e
1021
- $stderr.puts '// '+e.to_s
1066
+ debugger if debug :debug
1067
+ $stderr.puts "// #{e.to_s}: #{e.backtrace[0]}"
1022
1068
  return false
1023
1069
  end
1024
1070
 
@@ -1050,9 +1096,9 @@ module ActiveFacts
1050
1096
 
1051
1097
  next if role_sequences.compact.size != role_sequences.size # Role sequence missing; includes a derived fact type role
1052
1098
 
1053
- next unless make_joins('exclusion', name+(x_mandatory ? '/'+x_mandatory['Name'] : ''), role_sequences)
1099
+ next unless make_queries('exclusion', name+(x_mandatory ? '/'+x_mandatory['Name'] : ''), role_sequences)
1054
1100
 
1055
- ec = @constellation.SetExclusionConstraint(:new)
1101
+ ec = @constellation.SetExclusionConstraint(id_of(x))
1056
1102
  ec.vocabulary = @vocabulary
1057
1103
  ec.name = name
1058
1104
  # ec.enforcement =
@@ -1085,9 +1131,9 @@ module ActiveFacts
1085
1131
  # Role sequence missing; includes a derived fact type role
1086
1132
  next if role_sequences.compact.size != role_sequences.size
1087
1133
 
1088
- next unless make_joins('equality', name, role_sequences)
1134
+ next unless make_queries('equality', name, role_sequences)
1089
1135
 
1090
- ec = @constellation.SetEqualityConstraint(:new)
1136
+ ec = @constellation.SetEqualityConstraint(id_of(x))
1091
1137
  ec.vocabulary = @vocabulary
1092
1138
  ec.name = name
1093
1139
  # ec.enforcement =
@@ -1115,9 +1161,9 @@ module ActiveFacts
1115
1161
  )
1116
1162
  }
1117
1163
  next if role_sequences.compact.size != role_sequences.size # Role sequence missing; includes a derived fact type role
1118
- next unless make_joins('subset', name, role_sequences)
1164
+ next unless make_queries('subset', name, role_sequences)
1119
1165
 
1120
- ec = @constellation.SubsetConstraint(:new)
1166
+ ec = @constellation.SubsetConstraint(id_of(x))
1121
1167
  ec.vocabulary = @vocabulary
1122
1168
  ec.name = name
1123
1169
  # ec.enforcement =
@@ -1143,11 +1189,11 @@ module ActiveFacts
1143
1189
  end
1144
1190
  next unless from && to # Roles missing; covers a derived fact type
1145
1191
  if from.object_type != to.object_type
1146
- join_over, = *ActiveFacts::Metamodel.join_roles_over([from, to], :counterpart)
1192
+ join_over, = *ActiveFacts::Metamodel.plays_over([from, to], :counterpart)
1147
1193
  raise "Ring constraint has incompatible players #{from.object_type.name}, #{to.object_type.name}" if !join_over
1148
- debug :join, "join ring constraint over #{join_over.name}"
1194
+ debug :query, "join ring constraint over #{join_over.name}"
1149
1195
  end
1150
- rc = @constellation.RingConstraint(:new)
1196
+ rc = @constellation.RingConstraint(id_of(x))
1151
1197
  rc.vocabulary = @vocabulary
1152
1198
  rc.name = name
1153
1199
  # rc.enforcement =
@@ -1175,7 +1221,7 @@ module ActiveFacts
1175
1221
  next unless role # Role missing; belongs to a derived fact type
1176
1222
  debug :orm, "FrequencyConstraint(min #{min_frequency.inspect} max #{max_frequency.inspect} over #{role.fact_type.describe(role)} #{id} role ref = #{x_roles[0]["ref"]}"
1177
1223
  @by_id[id] = @constellation.PresenceConstraint(
1178
- :new,
1224
+ id_of(x_frequency_constraint),
1179
1225
  :vocabulary => @vocabulary,
1180
1226
  :name => name = x_frequency_constraint["Name"] || '',
1181
1227
  :role_sequence => role_sequence,
@@ -1208,7 +1254,7 @@ module ActiveFacts
1208
1254
  vt = @by_id[vt_id]
1209
1255
  throw "ValueType #{vtname} not found" unless vt
1210
1256
 
1211
- i = @constellation.Instance(:new, :population => population, :object_type => vt, :value => [v.text, is_a_string(v.text), nil])
1257
+ i = @constellation.Instance(id_of(v.parent), :population => population, :object_type => vt, :value => [v.text, is_literal_string(v.text), nil])
1212
1258
  @by_id[id] = i
1213
1259
  # show_xmlobj(v)
1214
1260
  }
@@ -1237,14 +1283,15 @@ module ActiveFacts
1237
1283
  throw "EntityType #{etname} not found" unless et
1238
1284
  end
1239
1285
 
1240
- instance = @constellation.Instance(:new, :population => population, :object_type => et, :value => nil)
1286
+ instance = @constellation.Instance(id_of(v), :population => population, :object_type => et, :value => nil)
1241
1287
  @by_id[id] = instance
1242
1288
  debug :orm, "Made new EntityType #{etname}"
1243
1289
  }
1244
1290
  end
1245
1291
 
1246
1292
  # The EntityType instances have implicit facts for the PI facts.
1247
- # We must create implicit PI facts after all the instances.
1293
+ # These are in the ORM file, but instead of using those,
1294
+ # We create implicit PI facts after all the instances.
1248
1295
  entity_count = 0
1249
1296
  pi_fact_count = 0
1250
1297
  debug :orm, "Creating identifying facts for entities" do
@@ -1294,6 +1341,7 @@ module ActiveFacts
1294
1341
  # Use the "ref" attribute of FactTypeRoleInstance:
1295
1342
  x_fact_roles = @x_model.xpath("orm:Facts/orm:Fact/orm:Instances/orm:FactTypeInstance/orm:RoleInstances/orm:FactTypeRoleInstance")
1296
1343
 
1344
+ # REVISIT: This presumably duplicates the identifying fact instances for the above entities. Hmmm.
1297
1345
  last_id = nil
1298
1346
  fact = nil
1299
1347
  fact_roles = []
@@ -1329,7 +1377,7 @@ module ActiveFacts
1329
1377
  debug :orm, "Reading diagrams" do
1330
1378
  x_diagrams.each do |x|
1331
1379
  name = (x["Name"] || '').strip
1332
- diagram = @constellation.Diagram(@vocabulary, name)
1380
+ diagram = @constellation.ORMDiagram(@vocabulary, name)
1333
1381
  debug :diagram, "Starting to read diagram #{name}"
1334
1382
  shapes = x.xpath("ormDiagram:Shapes/*")
1335
1383
  debug :orm, "Reading shapes" do
@@ -1346,28 +1394,28 @@ module ActiveFacts
1346
1394
  end
1347
1395
  when 'ExternalConstraintShape', 'FrequencyConstraintShape'
1348
1396
  # REVISIT: The offset might depend on the constraint type. This is right for subset and other round ones.
1349
- position = convert_position(bounds, Gravity::C)
1397
+ location = convert_location(bounds, Gravity::C)
1350
1398
  shape = @constellation.ConstraintShape(
1351
- :new, :diagram => diagram, :position => position, :is_expanded => is_expanded,
1399
+ :guid => id_of(x_shape), :orm_diagram => diagram, :location => location, :is_expanded => is_expanded,
1352
1400
  :constraint => subject
1353
1401
  )
1354
1402
  when 'RingConstraintShape'
1355
1403
  # REVISIT: The offset might depend on the ring constraint type. This is right for basic round ones.
1356
- position = convert_position(bounds, Gravity::C)
1404
+ location = convert_location(bounds, Gravity::C)
1357
1405
  shape = @constellation.RingConstraintShape(
1358
- :new, :diagram => diagram, :position => position, :is_expanded => is_expanded,
1406
+ :guid => id_of(x_shape), :orm_diagram => diagram, :location => location, :is_expanded => is_expanded,
1359
1407
  :constraint => subject
1360
1408
  )
1361
1409
  shape.fact_type = subject.role.fact_type
1362
1410
  when 'ModelNoteShape'
1363
1411
  # REVISIT: Add model notes
1364
1412
  when 'ObjectTypeShape'
1365
- position = convert_position(bounds, Gravity::C)
1366
- # $stderr.puts "#{subject.name}: bounds=#{bounds} -> position = (#{position.x}, #{position.y})"
1413
+ location = convert_location(bounds, Gravity::C)
1414
+ # $stderr.puts "#{subject.name}: bounds=#{bounds} -> location = (#{location.x}, #{location.y})"
1367
1415
  shape = @constellation.ObjectTypeShape(
1368
- :new, :diagram => diagram, :position => position, :is_expanded => is_expanded,
1416
+ :guid => id_of(x_shape), :orm_diagram => diagram, :location => location, :is_expanded => is_expanded,
1369
1417
  :object_type => subject,
1370
- :position => position
1418
+ :location => location
1371
1419
  )
1372
1420
  else
1373
1421
  raise "Unknown shape #{x_shape.name}"
@@ -1392,7 +1440,7 @@ module ActiveFacts
1392
1440
  else nil
1393
1441
  end
1394
1442
 
1395
- # Position of a fact type is the centre of the row of role boxes
1443
+ # Location of a fact type is the centre of the row of role boxes
1396
1444
  offs_x = 11
1397
1445
  offs_y = -12
1398
1446
  if fact_type.entity_type
@@ -1400,17 +1448,17 @@ module ActiveFacts
1400
1448
  offs_y -= 9 if !fact_type.entity_type.is_implied_by_objectification
1401
1449
  end
1402
1450
 
1403
- position = convert_position(bounds, Gravity::S, offs_x, offs_y)
1451
+ location = convert_location(bounds, Gravity::S, offs_x, offs_y)
1404
1452
 
1405
- # $stderr.puts "#{fact_type.describe}: bounds=#{bounds} -> position = (#{position.x}, #{position.y})"
1453
+ # $stderr.puts "#{fact_type.describe}: bounds=#{bounds} -> location = (#{location.x}, #{location.y})"
1406
1454
 
1407
1455
  debug :orm, "REVISIT: Can't place rotated fact type correctly on diagram yet" if rotation_setting
1408
1456
 
1409
- debug :orm, "fact type at #{position.x},#{position.y} has display_role_names_setting=#{display_role_names_setting.inspect}, rotation_setting=#{rotation_setting.inspect}"
1457
+ debug :orm, "fact type at #{location.x},#{location.y} has display_role_names_setting=#{display_role_names_setting.inspect}, rotation_setting=#{rotation_setting.inspect}"
1410
1458
  shape = @constellation.FactTypeShape(
1411
- :new,
1412
- :diagram => diagram,
1413
- :position => position,
1459
+ :guid => id_of(x_shape),
1460
+ :orm_diagram => diagram,
1461
+ :location => location,
1414
1462
  :is_expanded => is_expanded,
1415
1463
  :display_role_names_setting => display_role_names_setting,
1416
1464
  :rotation_setting => rotation_setting,
@@ -1433,18 +1481,23 @@ module ActiveFacts
1433
1481
 
1434
1482
  relative_shapes = x_shape.xpath('ormDiagram:RelativeShapes/*')
1435
1483
  relative_shapes.each do |xr_shape|
1436
- position = convert_position(xr_shape['AbsoluteBounds'])
1484
+ location = convert_location(xr_shape['AbsoluteBounds'])
1437
1485
  case xr_shape.name
1438
1486
  when 'ObjectifiedFactTypeNameShape'
1439
- @constellation.ObjectifiedFactTypeNameShape(shape, :guid => :new, :diagram => diagram, :position => position, :is_expanded => false)
1487
+ @constellation.ObjectifiedFactTypeNameShape(:guid => id_of(xr_shape), :fact_type_shape => shape, :orm_diagram => diagram, :location => location, :is_expanded => false)
1440
1488
  when 'ReadingShape'
1441
- @constellation.ReadingShape(shape, :guid => :new, :fact_type_shape=>shape, :diagram => diagram, :position => position, :is_expanded => false, :reading => fact_type.preferred_reading)
1489
+ begin
1490
+ @constellation.ReadingShape(:guid => id_of(xr_shape), :fact_type_shape => shape, :orm_diagram => diagram, :location => location, :is_expanded => false, :reading => fact_type.preferred_reading)
1491
+ rescue =>e
1492
+ debugger
1493
+ @constellation.ReadingShape(:guid => id_of(xr_shape), :fact_type_shape => shape, :orm_diagram => diagram, :location => location, :is_expanded => false, :reading => fact_type.preferred_reading)
1494
+ end
1442
1495
  when 'RoleNameShape'
1443
1496
  role = @by_id[xr_shape.xpath("ormDiagram:Subject")[0]['ref']]
1444
1497
  role_display = role_display_for_role(shape, x_role_display, role)
1445
1498
  debug :orm, "Fact type '#{fact_type.preferred_reading.expand}' has #{xr_shape.name}"
1446
1499
  @constellation.RoleNameShape(
1447
- :new, :diagram => diagram, :position => position, :is_expanded => false,
1500
+ :guid => id_of(xr_shape), :orm_diagram => diagram, :location => location, :is_expanded => false,
1448
1501
  :role_display => role_display
1449
1502
  )
1450
1503
  when 'ValueConstraintShape'
@@ -1455,7 +1508,7 @@ module ActiveFacts
1455
1508
  role_display = role_display_for_role(shape, x_role_display, constraint.role)
1456
1509
  debug :orm, "ValueConstraintShape is on #{role_display.ordinal}'th role (by #{x_role_display.size > 0 ? 'role_display' : 'fact roles'})"
1457
1510
  @constellation.ValueConstraintShape(
1458
- :new, :diagram => diagram, :position => position, :is_expanded => false,
1511
+ :guid => id_of(xr_shape), :orm_diagram => diagram, :location => location, :is_expanded => false,
1459
1512
  :constraint => constraint,
1460
1513
  :object_type_shape => nil, # This constraint is relative to a Fact Type, so must be on a role
1461
1514
  :role_display => role_display
@@ -1480,7 +1533,7 @@ module ActiveFacts
1480
1533
  end
1481
1534
 
1482
1535
  DIAGRAM_SCALE = 96*1.5
1483
- def convert_position(bounds, gravity = Gravity::C, xoffs = 0, yoffs = 0)
1536
+ def convert_location(bounds, gravity = Gravity::C, xoffs = 0, yoffs = 0)
1484
1537
  return nil unless bounds
1485
1538
  # Bounds is top, left, width, height in inches
1486
1539
  bf = bounds.split(/, /).map{|b|b.to_f}
@@ -1492,11 +1545,11 @@ module ActiveFacts
1492
1545
 
1493
1546
  x = (DIAGRAM_SCALE * (bf[0]+bf[2]*sizefrax[gravity][0]/2)).round + xoffs
1494
1547
  y = (DIAGRAM_SCALE * (bf[1]+bf[3]*sizefrax[gravity][1]/2)).round + yoffs
1495
- @constellation.Position(x, y)
1548
+ @constellation.Location(x, y)
1496
1549
  end
1497
1550
 
1498
1551
  # Detect numeric data and denote it as a string:
1499
- def is_a_string(value)
1552
+ def is_literal_string(value)
1500
1553
  value =~ /[^ \d.]/
1501
1554
  end
1502
1555