activefacts 0.8.9 → 0.8.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) hide show
  1. data/.gemtest +0 -0
  2. data/Manifest.txt +28 -33
  3. data/Rakefile +11 -12
  4. data/bin/cql +90 -46
  5. data/examples/CQL/Blog.cql +2 -1
  6. data/examples/CQL/CompanyDirectorEmployee.cql +2 -2
  7. data/examples/CQL/Death.cql +1 -1
  8. data/examples/CQL/Diplomacy.cql +9 -9
  9. data/examples/CQL/Genealogy.cql +3 -2
  10. data/examples/CQL/Insurance.cql +10 -7
  11. data/examples/CQL/JoinEquality.cql +2 -2
  12. data/examples/CQL/Marriage.cql +1 -1
  13. data/examples/CQL/Metamodel.cql +73 -53
  14. data/examples/CQL/MetamodelNext.cql +89 -67
  15. data/examples/CQL/OneToOnes.cql +2 -2
  16. data/examples/CQL/ServiceDirector.cql +10 -5
  17. data/examples/CQL/Supervision.cql +3 -3
  18. data/examples/CQL/Tests.Test5.Load.cql +1 -1
  19. data/examples/CQL/Warehousing.cql +4 -2
  20. data/lib/activefacts/cql/CQLParser.treetop +26 -60
  21. data/lib/activefacts/cql/Context.treetop +12 -2
  22. data/lib/activefacts/cql/Expressions.treetop +14 -30
  23. data/lib/activefacts/cql/FactTypes.treetop +165 -110
  24. data/lib/activefacts/cql/Language/English.treetop +167 -54
  25. data/lib/activefacts/cql/LexicalRules.treetop +16 -2
  26. data/lib/activefacts/cql/{Concepts.treetop → ObjectTypes.treetop} +36 -37
  27. data/lib/activefacts/cql/Terms.treetop +57 -27
  28. data/lib/activefacts/cql/ValueTypes.treetop +39 -13
  29. data/lib/activefacts/cql/compiler.rb +5 -3
  30. data/lib/activefacts/cql/compiler/{reading.rb → clause.rb} +407 -285
  31. data/lib/activefacts/cql/compiler/constraint.rb +178 -275
  32. data/lib/activefacts/cql/compiler/entity_type.rb +73 -64
  33. data/lib/activefacts/cql/compiler/expression.rb +418 -0
  34. data/lib/activefacts/cql/compiler/fact.rb +146 -145
  35. data/lib/activefacts/cql/compiler/fact_type.rb +197 -80
  36. data/lib/activefacts/cql/compiler/join.rb +159 -0
  37. data/lib/activefacts/cql/compiler/shared.rb +51 -23
  38. data/lib/activefacts/cql/compiler/value_type.rb +56 -2
  39. data/lib/activefacts/cql/parser.rb +15 -4
  40. data/lib/activefacts/generate/absorption.rb +7 -7
  41. data/lib/activefacts/generate/cql.rb +100 -37
  42. data/lib/activefacts/generate/oo.rb +28 -51
  43. data/lib/activefacts/generate/ordered.rb +60 -36
  44. data/lib/activefacts/generate/ruby.rb +6 -6
  45. data/lib/activefacts/generate/sql/server.rb +4 -4
  46. data/lib/activefacts/input/orm.rb +71 -53
  47. data/lib/activefacts/persistence.rb +1 -1
  48. data/lib/activefacts/persistence/columns.rb +27 -23
  49. data/lib/activefacts/persistence/foreignkey.rb +6 -6
  50. data/lib/activefacts/persistence/index.rb +17 -17
  51. data/lib/activefacts/persistence/{concept.rb → object_type.rb} +9 -9
  52. data/lib/activefacts/persistence/reference.rb +61 -36
  53. data/lib/activefacts/persistence/tables.rb +61 -59
  54. data/lib/activefacts/support.rb +54 -29
  55. data/lib/activefacts/version.rb +1 -1
  56. data/lib/activefacts/vocabulary/extensions.rb +99 -54
  57. data/lib/activefacts/vocabulary/metamodel.rb +43 -37
  58. data/lib/activefacts/vocabulary/verbaliser.rb +134 -109
  59. data/spec/absorption_spec.rb +8 -8
  60. data/spec/cql/comparison_spec.rb +91 -0
  61. data/spec/cql/contractions_spec.rb +251 -0
  62. data/spec/cql/entity_type_spec.rb +319 -0
  63. data/spec/cql/expressions_spec.rb +63 -0
  64. data/spec/cql/fact_type_matching_spec.rb +283 -0
  65. data/spec/cql/french_spec.rb +21 -0
  66. data/spec/cql/parser/bad_literals_spec.rb +86 -0
  67. data/spec/cql/parser/constraints_spec.rb +19 -0
  68. data/spec/cql/parser/entity_types_spec.rb +106 -0
  69. data/spec/cql/parser/expressions_spec.rb +179 -0
  70. data/spec/cql/parser/fact_types_spec.rb +41 -0
  71. data/spec/cql/parser/literals_spec.rb +312 -0
  72. data/spec/cql/parser/pragmas_spec.rb +89 -0
  73. data/spec/cql/parser/value_types_spec.rb +42 -0
  74. data/spec/cql/role_matching_spec.rb +147 -0
  75. data/spec/cql/samples_spec.rb +9 -9
  76. data/spec/cql_cql_spec.rb +1 -1
  77. data/spec/cql_dm_spec.rb +116 -0
  78. data/spec/cql_mysql_spec.rb +1 -1
  79. data/spec/cql_ruby_spec.rb +1 -1
  80. data/spec/cql_sql_spec.rb +3 -3
  81. data/spec/cql_symbol_tables_spec.rb +30 -30
  82. data/spec/cqldump_spec.rb +4 -4
  83. data/spec/helpers/array_matcher.rb +32 -27
  84. data/spec/helpers/diff_matcher.rb +6 -26
  85. data/spec/helpers/file_matcher.rb +41 -32
  86. data/spec/helpers/parse_to_ast_matcher.rb +76 -0
  87. data/spec/helpers/string_matcher.rb +32 -31
  88. data/spec/norma_cql_spec.rb +1 -1
  89. data/spec/norma_ruby_spec.rb +1 -1
  90. data/spec/norma_ruby_sql_spec.rb +1 -1
  91. data/spec/norma_sql_spec.rb +3 -1
  92. data/spec/norma_tables_spec.rb +1 -1
  93. data/spec/ruby_api_spec.rb +23 -0
  94. data/spec/spec_helper.rb +5 -4
  95. metadata +66 -66
  96. data/examples/CQL/OrienteeringER.cql +0 -58
  97. data/lib/activefacts/api.rb +0 -44
  98. data/lib/activefacts/api/concept.rb +0 -410
  99. data/lib/activefacts/api/constellation.rb +0 -128
  100. data/lib/activefacts/api/entity.rb +0 -256
  101. data/lib/activefacts/api/instance.rb +0 -60
  102. data/lib/activefacts/api/instance_index.rb +0 -80
  103. data/lib/activefacts/api/numeric.rb +0 -167
  104. data/lib/activefacts/api/role.rb +0 -80
  105. data/lib/activefacts/api/role_proxy.rb +0 -70
  106. data/lib/activefacts/api/role_values.rb +0 -117
  107. data/lib/activefacts/api/standard_types.rb +0 -87
  108. data/lib/activefacts/api/support.rb +0 -65
  109. data/lib/activefacts/api/value.rb +0 -135
  110. data/lib/activefacts/api/vocabulary.rb +0 -82
  111. data/spec/api/autocounter.rb +0 -82
  112. data/spec/api/constellation.rb +0 -130
  113. data/spec/api/entity_type.rb +0 -103
  114. data/spec/api/instance.rb +0 -461
  115. data/spec/api/roles.rb +0 -124
  116. data/spec/api/value_type.rb +0 -112
  117. data/spec/api_spec.rb +0 -13
  118. data/spec/cql/matching_spec.rb +0 -517
  119. data/spec/cql/unit_spec.rb +0 -394
  120. data/spec/spec.opts +0 -1
@@ -177,6 +177,8 @@ module ActiveFacts
177
177
  name = (x['Name'] || "").gsub(/\s+/,' ').gsub(/-/,'_').strip
178
178
  name = nil if name.size == 0
179
179
 
180
+ next if x['IsImplicitBooleanValue']
181
+
180
182
  cdt = x.xpath('orm:ConceptualDataType')[0]
181
183
  scale = cdt['Scale']
182
184
  scale = scale != "" && scale.to_i
@@ -244,6 +246,7 @@ module ActiveFacts
244
246
  name = "<unnamed>" if !name
245
247
  name = "" if !name || name.size == 0
246
248
  # Note that the new metamodel doesn't have a name for a facttype unless it's objectified
249
+ next if x.xpath("orm:DerivationRule").size > 0
247
250
 
248
251
  debug :orm, "FactType #{name || id}"
249
252
  facts << @by_id[id] = fact_type = @constellation.FactType(:new)
@@ -284,8 +287,7 @@ module ActiveFacts
284
287
  throw "For Subtype fact #{name}, the subtype #{subtype_id} was not found" if !subtype
285
288
  debug :orm, "#{subtype.name} is a subtype of #{supertype.name}"
286
289
 
287
- inheritance_fact = @constellation.TypeInheritance(subtype, supertype)
288
- inheritance_fact.fact_type_id = :new
290
+ inheritance_fact = @constellation.TypeInheritance(subtype, supertype, :fact_type_id => :new)
289
291
  if x["IsPrimary"] == "true" or # Old way
290
292
  x["PreferredIdentificationPath"] == "true" # Newer
291
293
  debug :orm, "#{supertype.name} is primary supertype of #{subtype.name}"
@@ -297,8 +299,8 @@ module ActiveFacts
297
299
  facts << @by_id[id] = inheritance_fact
298
300
 
299
301
  # Create the new Roles so we can find constraints on them:
300
- subtype_role = @by_id[subtype_role_id] = @constellation.Role(inheritance_fact, 0, :concept => subtype)
301
- supertype_role = @by_id[supertype_role_id] = @constellation.Role(inheritance_fact, 1, :concept => supertype)
302
+ subtype_role = @by_id[subtype_role_id] = @constellation.Role(inheritance_fact, 0, :object_type => subtype)
303
+ supertype_role = @by_id[supertype_role_id] = @constellation.Role(inheritance_fact, 1, :object_type => supertype)
302
304
 
303
305
  # Create readings, so constraints can be verbalised for example:
304
306
  rs = @constellation.RoleSequence(:new)
@@ -310,7 +312,7 @@ module ActiveFacts
310
312
  rs2 = @constellation.RoleSequence(:new)
311
313
  @constellation.RoleRef(rs2, 0, :role => supertype_role)
312
314
  @constellation.RoleRef(rs2, 1, :role => subtype_role)
313
- n = 'aeiouh'.include?(subtype_role.concept.name.downcase[0]) ? 1 : 0
315
+ n = 'aeiouh'.include?(subtype_role.object_type.name.downcase[0]) ? 1 : 0
314
316
  @constellation.Reading(inheritance_fact, 2+n, :role_sequence => rs2, :text => "{0} is a {1}")
315
317
  @constellation.Reading(inheritance_fact, 3-n, :role_sequence => rs2, :text => "{0} is an {1}")
316
318
  }
@@ -334,6 +336,7 @@ module ActiveFacts
334
336
 
335
337
  fact_id = x_fact_type['ref']
336
338
  fact_type = @by_id[fact_id]
339
+ next if x.xpath("orm:DerivationRule").size > 0
337
340
  throw "Nested fact #{fact_id} not found" if !fact_type
338
341
 
339
342
  #if is_implied
@@ -345,6 +348,8 @@ module ActiveFacts
345
348
  @nested_types <<
346
349
  @by_id[id] =
347
350
  nested_type = @constellation.EntityType(@vocabulary, name)
351
+ independent = x['IsIndependent']
352
+ nested_type.is_independent = true if independent && independent == 'true' && !is_implied
348
353
  nested_type.fact_type = fact_type
349
354
  end
350
355
  }
@@ -364,6 +369,7 @@ module ActiveFacts
364
369
  debug :orm, "Reading roles and readings" do
365
370
  @x_facts.each{|x|
366
371
  id = x['id']
372
+ next if x.xpath("orm:DerivationRule").size > 0
367
373
  fact_type = @by_id[id]
368
374
  fact_name = x['Name'] || x['_Name'] || ''
369
375
  #fact_name.gsub!(/\s/,'')
@@ -385,9 +391,8 @@ module ActiveFacts
385
391
  raise "Invalid ORM file; fact has missing player (RolePlayer id=#{id})" unless rp
386
392
  ref = rp['ref']
387
393
 
388
- # Find the concept that plays the role:
389
- concept = @by_id[ref]
390
- throw "RolePlayer for '#{name}' #{ref} was not found" if !concept
394
+ # Find the object_type that plays the role:
395
+ object_type = @by_id[ref]
391
396
 
392
397
  # Skip implicit roles added by NORMA to make unaries into binaries.
393
398
  # This would make constraints over the deleted roles impossible,
@@ -406,19 +411,19 @@ module ActiveFacts
406
411
  role_name = x['Name']
407
412
  other_role.role_name = role_name if role_name && role_name != ''
408
413
 
409
- concept.retract # Delete our object for the implicit boolean ValueType
410
414
  @by_id.delete(ref) # and de-index it from our list
411
415
  next
412
416
  end
417
+ throw "RolePlayer for '#{name}' #{ref} was not found" if !object_type
413
418
 
414
- debug :orm, "#{@vocabulary.name}, RoleName=#{x['Name'].inspect} played by concept=#{concept.name}"
415
- throw "Role is played by #{concept.class} not Concept" if !(@constellation.vocabulary.concept(:Concept) === concept)
419
+ debug :orm, "#{@vocabulary.name}, RoleName=#{x['Name'].inspect} played by object_type=#{object_type.name}"
420
+ throw "Role is played by #{object_type.class} not ObjectType" if !(@constellation.vocabulary.object_type(:ObjectType) === object_type)
416
421
 
417
- debug :orm, "Creating role #{name} nr#{fact_type.all_role.size} of #{fact_type.fact_type_id} played by #{concept.name}"
422
+ debug :orm, "Creating role #{name} nr#{fact_type.all_role.size} of #{fact_type.fact_type_id} played by #{object_type.name}"
418
423
 
419
- role = @by_id[id] = @constellation.Role(fact_type, fact_type.all_role.size, :concept => concept)
420
- role.role_name = name if name && name != concept.name
421
- debug :orm, "Fact #{fact_name} (id #{fact_type.fact_type_id.object_id}) role #{x['Name']} is played by #{concept.name}, role is #{role.object_id}"
424
+ role = @by_id[id] = @constellation.Role(fact_type, fact_type.all_role.size, :object_type => object_type)
425
+ role.role_name = name if name && name != object_type.name
426
+ debug :orm, "Fact #{fact_name} (id #{fact_type.fact_type_id.object_id}) role #{x['Name']} is played by #{object_type.name}, role is #{role.object_id}"
422
427
 
423
428
  x_vr = x.xpath("orm:ValueRestriction/orm:RoleValueConstraint")
424
429
  x_vr.each{|vr|
@@ -431,7 +436,7 @@ module ActiveFacts
431
436
  }
432
437
  }
433
438
 
434
- debug :orm, "Adding Role #{role.role_name || role.concept.name} to #{fact_type.describe}"
439
+ debug :orm, "Adding Role #{role.role_name || role.object_type.name} to #{fact_type.describe}"
435
440
  #fact_type.add_role(role)
436
441
  debug :orm, "Role #{role} is #{id}"
437
442
  }
@@ -482,7 +487,7 @@ module ActiveFacts
482
487
  #puts "text=#{text.inspect}, la=#{$1.inspect}, ta=#{$2.inspect}" if $1 || $2
483
488
  la = ($1||'').gsub(/\s+/,' ').sub(/-/,'').strip
484
489
  ta = ($2||'').gsub(/\s+/,' ').sub(/-/,'').strip
485
- #puts "Setting leading adj #{la.inspect} from #{text.inspect} for #{role_ref.role.concept.name}" if la != ""
490
+ #puts "Setting leading adj #{la.inspect} from #{text.inspect} for #{role_ref.role.object_type.name}" if la != ""
486
491
  # REVISIT: Dunno what's up here, but removing the "if" test makes this chuck exceptions:
487
492
  role_ref.leading_adjective = la if la != ""
488
493
  role_ref.trailing_adjective = ta if ta != ""
@@ -502,7 +507,7 @@ module ActiveFacts
502
507
  if RESERVED_WORDS.include?(w)
503
508
  $stderr.puts "Masking reserved word '#{w}' in reading '#{text}'"
504
509
  next "_#{w}"
505
- elsif @constellation.Concept[[[@vocabulary.name], w]]
510
+ elsif @constellation.ObjectType[[[@vocabulary.name], w]]
506
511
  $stderr.puts "Masking object type name '#{w}' in reading '#{text}'"
507
512
  next "_#{w}"
508
513
  elsif all_role_refs.detect{|rr| rr.role.role_name == w}
@@ -519,17 +524,17 @@ module ActiveFacts
519
524
  next ''
520
525
  end
521
526
  end
522
- $stderr.puts "Elided illegal characters '#{elided}' from reading" unless elided.empty?
527
+ $stderr.puts "Elided illegal characters '#{elided}' from reading #{text.inspect}" unless elided.empty?
523
528
  text
524
529
  end
525
530
 
526
531
  def get_role_sequence(role_array)
527
- # puts "Getting RoleSequence [#{role_array.map{|r| "#{r.concept.name} (role #{r.object_id})" }*", "}]"
532
+ # puts "Getting RoleSequence [#{role_array.map{|r| "#{r.object_type.name} (role #{r.object_id})" }*", "}]"
528
533
 
529
534
  # Look for an existing RoleSequence
530
535
  # REVISIT: This searches all role sequences. Perhaps we could narrow it down first instead?
531
536
  role_sequence = @constellation.RoleSequence.values.detect{|c|
532
- #puts "Checking RoleSequence [#{c.all_role_ref.map{|rr| rr.role.concept.name}*", "}]"
537
+ #puts "Checking RoleSequence [#{c.all_role_ref.map{|rr| rr.role.object_type.name}*", "}]"
533
538
  role_array == c.all_role_ref.sort_by{|rr| rr.ordinal}.map{|rr| rr.role }
534
539
  }
535
540
  # puts "Found matching RoleSequence!" if role_sequence
@@ -558,12 +563,15 @@ module ActiveFacts
558
563
  if (x_object.name.to_s == 'ObjectifiedType')
559
564
  x_nests = x_object.xpath('orm:NestedPredicate')[0]
560
565
  implied = x_nests['IsImplied']
566
+ # x_fact is the fact of which the role player is an objectification, not the fact this role belongs to
561
567
  x_fact = @x_by_id[x_nests['ref']]
562
568
  end
563
569
 
564
570
  # This might have been a role of an ImpliedFact, which makes it safe to ignore.
565
571
  next if 'ImpliedFact' == x_role.parent.parent.name
566
572
 
573
+ next if x_role.parent.parent.xpath('orm:DerivationRule').size > 0
574
+
567
575
  # Talk about why this wasn't found - this shouldn't happen.
568
576
  if (!x_nests || !implied)
569
577
  #puts "="*60
@@ -629,7 +637,7 @@ module ActiveFacts
629
637
  name = nil if name.size == 0
630
638
  #puts "Residual Mandatory #{name}: #{role_sequence.to_s}"
631
639
 
632
- if (players = role_sequence.all_role_ref.map{|rr| rr.role.concept}).uniq.size > 1
640
+ if (players = role_sequence.all_role_ref.map{|rr| rr.role.object_type}).uniq.size > 1
633
641
  join_over, = *ActiveFacts::Metamodel.join_roles_over(role_sequence.all_role_ref.map{|rr| rr.role}, :proximate)
634
642
  raise "Mandatory join constraint #{name} has incompatible players #{players.map{|o| o.name}.inspect}" unless join_over
635
643
  if players.detect{|p| p != join_over}
@@ -666,7 +674,7 @@ module ActiveFacts
666
674
  x_pi = x.xpath("orm:PreferredIdentifierFor")[0]
667
675
  pi = x_pi ? @by_id[eref = x_pi['ref']] : nil
668
676
 
669
- # Skip uniqueness constraints on implied concepts
677
+ # Skip uniqueness constraints on implied object_types
670
678
  next if x_pi && !pi
671
679
 
672
680
  # Get the RoleSequence:
@@ -680,7 +688,7 @@ module ActiveFacts
680
688
  if (fact_types = role_sequence.all_role_ref.map{|rr| rr.role.fact_type}).uniq.size > 1
681
689
  join_over, = *ActiveFacts::Metamodel.join_roles_over(role_sequence.all_role_ref.map{|rr| rr.role}, :counterpart)
682
690
 
683
- players = role_sequence.all_role_ref.map{|rr| rr.role.concept.name}.uniq
691
+ players = role_sequence.all_role_ref.map{|rr| rr.role.object_type.name}.uniq
684
692
  raise "Uniqueness join constraint #{name} has incompatible players #{players.inspect}" unless join_over
685
693
  subtyping = players.size > 1 ? 'subtyping ' : ''
686
694
  # REVISIT: Create the Join, the JoinNode for join_over, and steps from each role_ref to join_over
@@ -724,7 +732,7 @@ module ActiveFacts
724
732
  (role = rr.role) &&
725
733
  (fact_type = role.fact_type) &&
726
734
  fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance) &&
727
- role.concept == fact_type.supertype &&
735
+ role.object_type == fact_type.supertype &&
728
736
  fact_type.provides_identification
729
737
 
730
738
  pc = @constellation.PresenceConstraint(:new)
@@ -747,10 +755,10 @@ module ActiveFacts
747
755
  end
748
756
 
749
757
  def subtype_join_step(join, ti)
750
- subtype_node = join.all_join_node.detect{|jn| jn.concept == ti.subtype } ||
751
- @constellation.JoinNode(join, join.all_join_node.size, :concept => ti.subtype)
752
- supertype_node = join.all_join_node.detect{|jn| jn.concept == ti.supertype } ||
753
- @constellation.JoinNode(join, join.all_join_node.size, :concept => ti.supertype)
758
+ subtype_node = join.all_join_node.detect{|jn| jn.object_type == ti.subtype } ||
759
+ @constellation.JoinNode(join, join.all_join_node.size, :object_type => ti.subtype)
760
+ supertype_node = join.all_join_node.detect{|jn| jn.object_type == ti.supertype } ||
761
+ @constellation.JoinNode(join, join.all_join_node.size, :object_type => ti.supertype)
754
762
  rs = @constellation.RoleSequence(:new)
755
763
  @constellation.RoleRef(rs, 0, :role => ti.subtype_role)
756
764
  sub_jr = @constellation.JoinRole(subtype_node, ti.subtype_role)
@@ -793,8 +801,11 @@ module ActiveFacts
793
801
  end_joins = [] # An array of booleans indicating whether any role_sequence requires a subtyping join
794
802
  role_sequences[0].all_role_ref.size.times do |i|
795
803
  role_refs = role_sequences.map{|rs| rs.all_role_ref.detect{|rr| rr.ordinal == i}}
796
- next if (fact_types = role_refs.map{|rr| rr.role.fact_type}).uniq.size == 1
797
- if (players = role_refs.map{|rr| rr.role.concept}).uniq.size == 1
804
+ if (fact_types = role_refs.map{|rr| rr.role.fact_type}).uniq.size == 1
805
+ raise "In #{constraint_type} #{name}, there is a faulty join"
806
+ next
807
+ end
808
+ if (players = role_refs.map{|rr| rr.role.object_type}).uniq.size == 1
798
809
  end_point = players[0]
799
810
  end_joins[i] = false
800
811
  else
@@ -805,7 +816,7 @@ module ActiveFacts
805
816
  end
806
817
  end_point = common_supertypes[0]
807
818
 
808
- raise "constrained roles of #{constraint_type} constraint #{name} are incompatible (#{names*', '})" if common_supertypes.size == 0
819
+ raise "constrained roles of #{constraint_type} constraint #{name} are incompatible (#{players.map(&:name)*', '})" if common_supertypes.size == 0
809
820
  end_joins[i] = true
810
821
  end
811
822
  end_points[i] = end_point
@@ -849,7 +860,7 @@ module ActiveFacts
849
860
  role_sequences.zip(sequence_join_over||[], sequence_joined_roles||[]).map do |role_sequence, join_over, joined_roles|
850
861
  # Skip if there's no join here (sequence join nor end-point subset join)
851
862
  role_refs = role_sequence.all_role_ref_in_order
852
- if !join_over and !role_refs.detect{|rr| rr.role.concept != end_points[rr.ordinal]}
863
+ if !join_over and !role_refs.detect{|rr| rr.role.object_type != end_points[rr.ordinal]}
853
864
  # No sequence join nor end_point join here
854
865
  next
855
866
  end
@@ -866,8 +877,9 @@ module ActiveFacts
866
877
 
867
878
  # Create a join node for the actual end-point (supertype of the constrained roles)
868
879
  end_point = end_points[i]
880
+ raise "In #{constraint_type} #{name}, there is a faulty join" unless end_point
869
881
  debug :join, "Join Node #{join.all_join_node.size} is for #{end_point.name}"
870
- end_node = @constellation.JoinNode(join, join.all_join_node.size, :concept => end_point)
882
+ end_node = @constellation.JoinNode(join, join.all_join_node.size, :object_type => end_point)
871
883
 
872
884
  # We're going to rewrite the constraint to constrain the supertype roles, but assume they're the same:
873
885
  role_node = end_node
@@ -876,7 +888,7 @@ module ActiveFacts
876
888
  # Create subtyping join steps at the end-point, if needed:
877
889
  projecting_jr = nil
878
890
  constrained_join_role = nil
879
- if (subtype = role_ref.role.concept) != end_point
891
+ if (subtype = role_ref.role.object_type) != end_point
880
892
  debug :join, "Making subtyping join steps from #{subtype.name} to #{end_point.name}" do
881
893
  # There may be more than one supertyping level. Make the steps:
882
894
  subtyping_steps = subtype_join_steps(join, subtype, end_point)
@@ -884,14 +896,14 @@ module ActiveFacts
884
896
  constrained_join_role = subtyping_steps[-1].input_join_role
885
897
 
886
898
  # Replace the constrained role and node with the supertype ones:
887
- end_node = join.all_join_node.detect{|jn| jn.concept == end_point }
899
+ end_node = join.all_join_node.detect{|jn| jn.object_type == end_point }
888
900
  projecting_jr = js.output_join_role
889
- end_role = js.fact_type.all_role.detect{|r| r.concept == end_point }
890
- role_node = join.all_join_node.detect{|jn| jn.concept == role_ref.role.concept }
901
+ end_role = js.fact_type.all_role.detect{|r| r.object_type == end_point }
902
+ role_node = join.all_join_node.detect{|jn| jn.object_type == role_ref.role.object_type }
891
903
  end
892
904
  end
893
905
 
894
- raise "Internal error: making illegal reference to join node" if end_role.concept != end_node.concept
906
+ raise "Internal error: making illegal reference to join node" if end_role.object_type != end_node.object_type
895
907
  rr = @constellation.RoleRef(replacement_rs, replacement_rs.all_role_ref.size, :role => end_role)
896
908
  projecting_jr ||= (constrained_join_role = @constellation.JoinRole(end_node, end_role))
897
909
  projecting_jr.role_ref = rr # Project this RoleRef
@@ -899,15 +911,15 @@ module ActiveFacts
899
911
  if join_over
900
912
  if !join_node # Create the JoinNode when processing the first role
901
913
  debug :join, "Join Node #{join.all_join_node.size} is over #{join_over.name}"
902
- join_node = @constellation.JoinNode(join, join.all_join_node.size, :concept => join_over)
914
+ join_node = @constellation.JoinNode(join, join.all_join_node.size, :object_type => join_over)
903
915
  end
904
916
  debug :join, "Making join step from #{end_point.name} to #{join_over.name}" do
905
917
  rs = @constellation.RoleSequence(:new)
906
918
  # Detect the fact type over which we're joining (may involve objectification)
907
- raise "Internal error: making illegal reference to join node" if role_ref.role.concept != role_node.concept
919
+ raise "Internal error: making illegal reference to join node" if role_ref.role.object_type != role_node.object_type
908
920
  @constellation.RoleRef(rs, 0, :role => role_ref.role)
909
921
  role_jr = @constellation.JoinRole(role_node, role_ref.role)
910
- raise "Internal error: making illegal reference to join node" if joined_role.concept != join_node.concept
922
+ raise "Internal error: making illegal reference to join node" if joined_role.object_type != join_node.object_type
911
923
  @constellation.RoleRef(rs, 1, :role => joined_role)
912
924
  join_jr = @constellation.JoinRole(join_node, joined_role)
913
925
 
@@ -919,13 +931,13 @@ module ActiveFacts
919
931
  if (roles = role_ref.role.fact_type.all_role.to_a).size > 1
920
932
  # Here we have an end join (step already created) but no sequence join
921
933
  if join_node
922
- raise "Internal error: making illegal join step" if role_ref.role.concept != role_node.concept
934
+ raise "Internal error: making illegal join step" if role_ref.role.object_type != role_node.object_type
923
935
  join_jr = @constellation.JoinRole(join_node, join_role)
924
936
  role_jr = @constellation.JoinRole(role_node, role_ref.role)
925
937
  js = @constellation.JoinStep(join_jr, role_jr, :fact_type => role_ref.role.fact_type)
926
938
  roles -= [join_role, role_ref.role]
927
939
  roles.each do |incidental_role|
928
- jn = @constellation.JoinNode(join, join.all_join_node.size, :concept => incidental_role.concept)
940
+ jn = @constellation.JoinNode(join, join.all_join_node.size, :object_type => incidental_role.object_type)
929
941
  jr = @constellation.JoinRole(jn, incidental_role, :join_step => js)
930
942
  end
931
943
  else
@@ -941,7 +953,7 @@ module ActiveFacts
941
953
  role_ref.role.fact_type.all_role.each do |role|
942
954
  next if role == role_jr.role
943
955
  next if role_sequence.all_role_ref.detect{|rr| rr.role == role}
944
- jn = @constellation.JoinNode(join, join.all_join_node.size, :concept => role.concept)
956
+ jn = @constellation.JoinNode(join, join.all_join_node.size, :object_type => role.object_type)
945
957
  jr = @constellation.JoinRole(jn, role)
946
958
  if js
947
959
  jr.join_step = js # Incidental role
@@ -994,6 +1006,8 @@ module ActiveFacts
994
1006
  @mandatory_constraints_by_rs.delete(mc_rs)
995
1007
  end
996
1008
 
1009
+ next if role_sequences.compact.size != role_sequences.size # Role sequence missing; includes a derived fact type role
1010
+
997
1011
  make_joins('exclusion', name+(x_mandatory ? '/'+x_mandatory['Name'] : ''), role_sequences)
998
1012
 
999
1013
  ec = @constellation.SetExclusionConstraint(:new)
@@ -1026,6 +1040,7 @@ module ActiveFacts
1026
1040
  )
1027
1041
  }
1028
1042
 
1043
+ next if role_sequences.compact.size != role_sequences.size # Role sequence missing; includes a derived fact type role
1029
1044
  make_joins('equality', name, role_sequences)
1030
1045
 
1031
1046
  ec = @constellation.SetEqualityConstraint(:new)
@@ -1055,6 +1070,7 @@ module ActiveFacts
1055
1070
  "equality constraint #{name}"
1056
1071
  )
1057
1072
  }
1073
+ next if role_sequences.compact.size != role_sequences.size # Role sequence missing; includes a derived fact type role
1058
1074
  make_joins('subset', name, role_sequences)
1059
1075
 
1060
1076
  ec = @constellation.SubsetConstraint(:new)
@@ -1081,9 +1097,10 @@ module ActiveFacts
1081
1097
  map do |xr|
1082
1098
  @by_id[xr['ref']]
1083
1099
  end
1084
- if from.concept != to.concept
1100
+ next unless from && to # Roles missing; covers a derived fact type
1101
+ if from.object_type != to.object_type
1085
1102
  join_over, = *ActiveFacts::Metamodel.join_roles_over([from, to], :counterpart)
1086
- raise "Ring constraint has incompatible players #{from.concept.name}, #{to.concept.name}" if !join_over
1103
+ raise "Ring constraint has incompatible players #{from.object_type.name}, #{to.object_type.name}" if !join_over
1087
1104
  debug :join, "join ring constraint over #{join_over.name}"
1088
1105
  end
1089
1106
  rc = @constellation.RingConstraint(:new)
@@ -1111,6 +1128,7 @@ module ActiveFacts
1111
1128
  role = @by_id[x_roles[0]["ref"]]
1112
1129
  role_sequence = @constellation.RoleSequence(:new)
1113
1130
  role_ref = @constellation.RoleRef(role_sequence, 0, :role => role)
1131
+ next unless role # Role missing; belongs to a derived fact type
1114
1132
  debug :orm, "FrequencyConstraint(min #{min_frequency.inspect} max #{max_frequency.inspect} over #{role.fact_type.describe(role)} #{id} role ref = #{x_roles[0]["ref"]}"
1115
1133
  @by_id[id] = @constellation.PresenceConstraint(
1116
1134
  :new,
@@ -1146,7 +1164,7 @@ module ActiveFacts
1146
1164
  vt = @by_id[vt_id]
1147
1165
  throw "ValueType #{vtname} not found" unless vt
1148
1166
 
1149
- i = @constellation.Instance(:new, :population => population, :concept => vt, :value => [v.text, is_a_string(v.text), nil])
1167
+ i = @constellation.Instance(:new, :population => population, :object_type => vt, :value => [v.text, is_a_string(v.text), nil])
1150
1168
  @by_id[id] = i
1151
1169
  # show_xmlobj(v)
1152
1170
  }
@@ -1175,7 +1193,7 @@ module ActiveFacts
1175
1193
  throw "EntityType #{etname} not found" unless et
1176
1194
  end
1177
1195
 
1178
- instance = @constellation.Instance(:new, :population => population, :concept => et, :value => nil)
1196
+ instance = @constellation.Instance(:new, :population => population, :object_type => et, :value => nil)
1179
1197
  @by_id[id] = instance
1180
1198
  debug :orm, "Made new EntityType #{etname}"
1181
1199
  }
@@ -1212,7 +1230,7 @@ module ActiveFacts
1212
1230
  debug :orm, "For FactType #{ft}" do
1213
1231
  fact = @constellation.Fact(:new, :population => population, :fact_type => ft)
1214
1232
  fact_roles = ft.all_role.map do |role|
1215
- if role.concept == et
1233
+ if role.object_type == et
1216
1234
  object = instance
1217
1235
  else
1218
1236
  object = role_instances[role]
@@ -1299,7 +1317,7 @@ module ActiveFacts
1299
1317
  when 'ObjectTypeShape'
1300
1318
  shape = @constellation.ObjectTypeShape(
1301
1319
  :new, :diagram => diagram, :position => position, :is_expanded => is_expanded,
1302
- :concept => subject,
1320
+ :object_type => subject,
1303
1321
  :has_expanded_reference_mode => false # REVISIT
1304
1322
  )
1305
1323
  else
@@ -1350,9 +1368,9 @@ module ActiveFacts
1350
1368
  )
1351
1369
  # Create RoleDisplay objects if necessary
1352
1370
  x_role_display = x_shape.xpath("ormDiagram:RoleDisplayOrder/ormDiagram:Role")
1353
- # print "Fact type '#{fact_type.preferred_reading.expand}' (#{fact_type.all_role.map{|r|r.concept.name}*' '})"
1371
+ # print "Fact type '#{fact_type.preferred_reading.expand}' (#{fact_type.all_role.map{|r|r.object_type.name}*' '})"
1354
1372
  if x_role_display.size > 0
1355
- debug :orm, " has roleDisplay (#{x_role_display.map{|rd| @by_id[rd['ref']].concept.name}*','})'"
1373
+ debug :orm, " has roleDisplay (#{x_role_display.map{|rd| @by_id[rd['ref']].object_type.name}*','})'"
1356
1374
  x_role_display.each_with_index do |rd, ordinal|
1357
1375
  role_display = @constellation.RoleDisplay(shape, ordinal, :role => @by_id[rd['ref']])
1358
1376
  end
@@ -12,4 +12,4 @@ require 'activefacts/persistence/foreignkey'
12
12
  require 'activefacts/persistence/index'
13
13
 
14
14
  # These extend the API classes with relational awareness:
15
- require 'activefacts/persistence/concept'
15
+ require 'activefacts/persistence/object_type'
@@ -4,12 +4,12 @@
4
4
  #
5
5
  # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
6
  #
7
- # Each Reference from a Concept creates one or more Columns.
7
+ # Each Reference from a ObjectType creates one or more Columns.
8
8
  # A reference to a simple valuetype creates a single column, as
9
9
  # does a reference to a table entity identified by a single value.
10
10
  #
11
- # When referring to a concept that doesn't have its own table,
12
- # all references from that concept are absorbed into this one.
11
+ # When referring to a object_type that doesn't have its own table,
12
+ # all references from that object_type are absorbed into this one.
13
13
  #
14
14
  # When multiple values identify an entity that does have its own
15
15
  # table, a reference to that entity creates multiple columns,
@@ -63,12 +63,16 @@ module ActiveFacts
63
63
  # * If the names retained so far end in XYZ and the to_names start with XYZ, remove the duplication
64
64
  # * If we have retained the name of an entity, and this reference is the sole identifying role of an entity, and the identifying object has a name that is prefixed by the name of the object it identifies, remove the prefix and use just the suffix.
65
65
  def name(joiner = "")
66
+ self.class.name(@references, joiner)
67
+ end
68
+
69
+ def self.name(refs, joiner = "")
66
70
  last_names = []
67
- names = @references.
71
+ names = refs.
68
72
  inject([]) do |a, ref|
69
73
 
70
74
  # Skip any object after the first which is identified by this reference
71
- if ref != @references[0] and
75
+ if ref != refs[0] and
72
76
  !ref.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance) and
73
77
  ref.to and
74
78
  ref.to.is_a?(ActiveFacts::Metamodel::EntityType) and
@@ -99,8 +103,8 @@ module ActiveFacts
99
103
  names.shift
100
104
  end
101
105
 
102
- # If the reference is to the single identifying role of the concept making the reference,
103
- # strip the concept name from the start of the reference role
106
+ # If the reference is to the single identifying role of the object_type making the reference,
107
+ # strip the object_type name from the start of the reference role
104
108
  if a.size > 0 and
105
109
  (et = ref.from).is_a?(ActiveFacts::Metamodel::EntityType) and
106
110
  # This instead of the next 2 would apply to all identifying roles, but breaks some examples:
@@ -209,10 +213,10 @@ module ActiveFacts
209
213
  end
210
214
 
211
215
  module Metamodel #:nodoc:
212
- # The Concept class is defined in the metamodel; full documentation is not generated.
216
+ # The ObjectType class is defined in the metamodel; full documentation is not generated.
213
217
  # This section shows the features relevant to relational Persistence.
214
- class Concept
215
- # The array of columns for this Concept's table
218
+ class ObjectType
219
+ # The array of columns for this ObjectType's table
216
220
  def columns
217
221
  @columns
218
222
  end
@@ -225,7 +229,7 @@ module ActiveFacts
225
229
 
226
230
  # The ValueType class is defined in the metamodel; full documentation is not generated.
227
231
  # This section shows the features relevant to relational Persistence.
228
- class ValueType < Concept
232
+ class ValueType < ObjectType
229
233
  # The identifier_columns for a ValueType can only ever be the self-value role that was injected
230
234
  def identifier_columns
231
235
  debug :columns, "Identifier Columns for #{name}" do
@@ -274,7 +278,7 @@ module ActiveFacts
274
278
 
275
279
  # The EntityType class is defined in the metamodel; full documentation is not generated.
276
280
  # This section shows the features relevant to relational Persistence.
277
- class EntityType < Concept
281
+ class EntityType < ObjectType
278
282
  # The identifier_columns for an EntityType are the columns that result from the identifying roles
279
283
  def identifier_columns
280
284
  debug :columns, "Identifier Columns for #{name}" do
@@ -303,7 +307,7 @@ module ActiveFacts
303
307
  (all_type_inheritance_as_subtype.size == 0 ||
304
308
  all_type_inheritance_as_subtype.detect{|ti| ti.provides_identification })
305
309
  rc = absorbed_via.from.reference_columns(excluded_supertypes)
306
- # The absorbed_via reference gets skipped here, ans also in concept.rb
310
+ # The absorbed_via reference gets skipped here, ans also in object_type.rb
307
311
  debug :columns, "Skipping #{absorbed_via}"
308
312
  #rc.each{|col| col.prepend(absorbed_via)}
309
313
  return rc
@@ -363,8 +367,8 @@ module ActiveFacts
363
367
  # Make schema transformations like adding ValueType self-value columns (and later, Rails-friendly ID fields).
364
368
  # Override this method to change the transformations
365
369
  def finish_schema
366
- all_concept.each do |concept|
367
- concept.self_value_reference if concept.is_a?(ActiveFacts::Metamodel::ValueType) && concept.is_table
370
+ all_object_type.each do |object_type|
371
+ object_type.self_value_reference if object_type.is_a?(ActiveFacts::Metamodel::ValueType) && object_type.is_table
368
372
  end
369
373
  end
370
374
 
@@ -373,18 +377,18 @@ module ActiveFacts
373
377
  finish_schema
374
378
 
375
379
  debug :columns, "Populating all columns" do
376
- all_concept.each do |concept|
377
- next if !concept.is_table
378
- debug :columns, "Populating columns for table #{concept.name}" do
379
- concept.populate_columns
380
+ all_object_type.each do |object_type|
381
+ next if !object_type.is_table
382
+ debug :columns, "Populating columns for table #{object_type.name}" do
383
+ object_type.populate_columns
380
384
  end
381
385
  end
382
386
  end
383
387
  debug :columns, "Finished columns" do
384
- all_concept.each do |concept|
385
- next if !concept.is_table
386
- debug :columns, "Finished columns for table #{concept.name}" do
387
- concept.columns.each do |column|
388
+ all_object_type.each do |object_type|
389
+ next if !object_type.is_table
390
+ debug :columns, "Finished columns for table #{object_type.name}" do
391
+ object_type.columns.each do |column|
388
392
  debug :columns, "#{column}"
389
393
  end
390
394
  end