activefacts 0.8.9 → 0.8.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
@@ -7,7 +7,7 @@
7
7
  #
8
8
  #module ActiveFacts
9
9
  $debug_indent = nil
10
- $debug_nested = false
10
+ $debug_nested = false # Set when a block enables all enclosed debugging
11
11
  $debug_keys = nil
12
12
  $debug_available = {}
13
13
 
@@ -46,40 +46,58 @@
46
46
  end
47
47
 
48
48
  def debug_selected(args)
49
- # Figure out whether this trace is enabled and nests:
50
- control = (!args.empty? && Symbol === args[0]) ? args.shift : :all
51
- key = control.to_s.sub(/_\Z/, '').to_sym
52
- $debug_available[key] ||= key
53
- enabled = $debug_nested || $debug_keys[key] || $debug_keys[:all]
54
- nesting = control.to_s =~ /_\Z/
55
- old_nested = $debug_nested
56
- $debug_nested = nesting
57
- [(enabled ? 1 : 0), $debug_keys[:all] ? " %-15s"%control : nil, old_nested]
49
+ # Figure out whether this trace is enabled (itself or by :all), if it nests, and if we should print the key:
50
+ key =
51
+ if Symbol === args[0]
52
+ control = args.shift
53
+ if (s = control.to_s) =~ /_\Z/
54
+ nested = true
55
+ s.sub(/_\Z/, '').to_sym # Avoid creating new strings willy-nilly
56
+ else
57
+ control
58
+ end
59
+ else
60
+ :all
61
+ end
62
+
63
+ $debug_available[key] ||= key # Remember that this debug was requested, for help
64
+ enabled = $debug_nested || # This debug is enabled because it's in a nested block
65
+ $debug_keys[key] || # This debug is enabled in its own right
66
+ $debug_keys[:all] # This debug is enabled because all are
67
+ $debug_nested = nested
68
+ [
69
+ (enabled ? 1 : 0),
70
+ $debug_keys[:all] ? " %-15s"%control : nil
71
+ ]
58
72
  end
59
73
 
60
- def debug(*args, &block)
74
+ def debug_show(*args)
61
75
  debug_initialize unless $debug_indent
62
76
 
63
- enabled, show_key, old_nested = debug_selected(args)
77
+ enabled, key_to_show = debug_selected(args)
64
78
 
65
79
  # Emit the message if enabled or a parent is:
66
80
  if args.size > 0 && enabled == 1
67
- puts "\##{show_key} "+" "*$debug_indent + args.join(' ')
81
+ puts "\##{key_to_show} " +
82
+ ' '*$debug_indent +
83
+ args.
84
+ # A laudable aim, certainly, but in practise the Procs leak and slow things down:
85
+ # map{|a| a.respond_to?(:call) ? a.call : a}.
86
+ join(' ')
68
87
  end
88
+ $debug_indent += enabled
89
+ enabled
90
+ end
69
91
 
70
- if block
71
- begin
72
- $debug_indent += enabled
73
- return yield # Return the value of the block
74
- ensure
75
- $debug_indent -= enabled
76
- $debug_nesting = old_nested
77
- end
78
- else
79
- r = enabled == 1 # If no block, return whether enabled
92
+ def debug(*args, &block)
93
+ begin
94
+ old_indent, old_nested, enabled = $debug_indent, $debug_nested, debug_show(*args)
95
+ return (block || proc { enabled == 1 }).call
96
+ ensure
97
+ $debug_indent, $debug_nested = old_indent, old_nested
80
98
  end
81
- r
82
99
  end
100
+
83
101
  #end
84
102
 
85
103
  # Return all duplicate objects in the array (using hash-equality)
@@ -94,10 +112,17 @@ class Array
94
112
  end.keys
95
113
  end
96
114
 
97
- # Allow indexing using a custom comparator:
98
- def index value, &compare_block
99
- compare_block ||= lambda{|a,b| a == b}
100
- (0...size).detect{|i| compare_block[value, self[i]] }
115
+ if RUBY_VERSION =~ /^1\.8/
116
+ # Fake up Ruby 1.9's Array#index method, mostly
117
+ alias_method :__orig_index, :index
118
+ def index *a, &b
119
+ if a.size == 0
120
+ raise "Not faking Enumerator for #{RUBY_VERSION}" if !b
121
+ (0...size).detect{|i| return i if b.call(self[i]) }
122
+ else
123
+ __orig_index(*a, &b)
124
+ end
125
+ end
101
126
  end
102
127
 
103
128
  # If any element, or sequence of elements, repeats immediately, delete the repetition.
@@ -109,7 +134,7 @@ class Array
109
134
  while i < size # Need to re-evaluate size on each loop - the array shrinks.
110
135
  j = i
111
136
  #puts "Looking for repetitions of #{self[i]}@[#{i}]"
112
- while tail = self[j+1..-1] and k = tail.index(self[i], &compare_block)
137
+ while tail = self[j+1..-1] and k = tail.index {|e| compare_block.call(e, self[i]) }
113
138
  length = j+1+k-i
114
139
  #puts "Found at #{j+1+k} (subsequence of length #{j+1+k-i}), will need to repeat to #{j+k+length}"
115
140
  if j+k+1+length <= size && compare_block[self[i, length], self[j+k+1, length]]
@@ -5,5 +5,5 @@
5
5
  # Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
6
6
  #
7
7
  module ActiveFacts
8
- VERSION = '0.8.9'
8
+ VERSION = '0.8.10'
9
9
  end
@@ -13,9 +13,9 @@ module ActiveFacts
13
13
  end
14
14
 
15
15
  def preferred_reading
16
- p = all_reading_by_ordinal[0]
17
- raise "No reading for (#{all_role.map{|r| r.concept.name}*", "})" unless p
18
- p
16
+ pr = all_reading_by_ordinal[0]
17
+ raise "No reading for (#{all_role.map{|r| r.object_type.name}*", "})" unless pr
18
+ pr
19
19
  end
20
20
 
21
21
  def describe(highlight = nil)
@@ -40,12 +40,12 @@ module ActiveFacts
40
40
  # This entity type has just objectified a fact type. Create the necessary ImplicitFactTypes with phantom roles
41
41
  def create_implicit_fact_type_for_unary
42
42
  role = all_role.single
43
- next if role.implicit_fact_type # Already exists
43
+ return if role.implicit_fact_type # Already exists
44
44
  # NORMA doesn't create an implicit fact type here, rather the fact type has an implicit extra role, so looks like a binary
45
45
  # We only do it when the unary fact type is not objectified
46
- implicit_fact_type = @constellation.ImplicitFactType(:new, :role => role)
47
- entity_type = @entity_type || @constellation.ImplicitBooleanValueType(role.concept.vocabulary, "_ImplicitBooleanValueType")
48
- phantom_role = @constellation.Role(implicit_fact_type, 0, :concept => entity_type)
46
+ implicit_fact_type = @constellation.ImplicitFactType(:new, :implying_role => role)
47
+ entity_type = @entity_type || @constellation.ImplicitBooleanValueType(role.object_type.vocabulary, "_ImplicitBooleanValueType")
48
+ phantom_role = @constellation.Role(implicit_fact_type, 0, :object_type => entity_type)
49
49
  end
50
50
 
51
51
  def reading_preferably_starting_with_role role
@@ -57,7 +57,7 @@ module ActiveFacts
57
57
 
58
58
  class Role
59
59
  def describe(highlight = nil)
60
- concept.name + (self == highlight ? "*" : "")
60
+ object_type.name + (self == highlight ? "*" : "")
61
61
  end
62
62
 
63
63
  # Is there are internal uniqueness constraint on this role only?
@@ -85,6 +85,33 @@ module ActiveFacts
85
85
  def preferred_reference
86
86
  fact_type.preferred_reading.role_sequence.all_role_ref.detect{|rr| rr.role == self }
87
87
  end
88
+
89
+ # Return true if this role is functional (has only one instance wrt its player)
90
+ # A role in an objectified fact type is deemed to refer to the implicit role of the objectification.
91
+ def is_functional
92
+ fact_type.entity_type or
93
+ fact_type.all_role.size != 2 or
94
+ all_role_ref.detect do |rr|
95
+ rr.role_sequence.all_role_ref.size == 1 and
96
+ rr.role_sequence.all_presence_constraint.detect do |pc|
97
+ pc.max_frequency == 1 and !pc.enforcement # Alethic uniqueness constraint
98
+ end
99
+ end
100
+ end
101
+
102
+ def role_method
103
+ if fact_type.all_role.size == 1
104
+ # The object of an objectified unary has no boolean; the existence of the object is the fact
105
+ return nil if fact_type.entity_type
106
+ return preferred_role_name(role)
107
+ end
108
+ if fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
109
+ # No method is available to indicate that the object is the specified subtype
110
+ # In future, this might be implemented using the type discriminator
111
+ return nil
112
+ end
113
+ end
114
+
88
115
  end
89
116
 
90
117
  class RoleRef
@@ -100,15 +127,28 @@ module ActiveFacts
100
127
  name_array =
101
128
  if role.fact_type.all_role.size == 1
102
129
  if role.fact_type.is_a?(ImplicitFactType)
103
- "#{role.concept.name} phantom for #{role.fact_type.role.concept.name}"
130
+ "#{role.object_type.name} phantom for #{role.fact_type.role.object_type.name}"
104
131
  else
105
132
  role.fact_type.preferred_reading.text.gsub(/\{[0-9]\}/,'').strip.split(/\s/)
106
133
  end
107
134
  else
108
- role.role_name || [leading_adjective, role.concept.name, trailing_adjective].compact.map{|w| w.split(/\s/)}.flatten
135
+ role.role_name || [leading_adjective, role.object_type.name, trailing_adjective].compact.map{|w| w.split(/\s/)}.flatten
109
136
  end
110
137
  return joiner ? Array(name_array)*joiner : Array(name_array)
111
138
  end
139
+
140
+ def cql_name
141
+ if role.fact_type.all_role.size == 1
142
+ role_name
143
+ elsif role.role_name
144
+ role.role_name
145
+ else
146
+ # Where an adjective has multiple words, the hyphen is inserted outside the outermost space, leaving the space
147
+ (leading_adjective ? leading_adjective.strip.sub(/ |$/, '-\0').sub(/[^-]$/,'\0 ') : '') +
148
+ role.object_type.name+
149
+ (trailing_adjective ? ' '+trailing_adjective.strip.sub(/.* |^/, '\0-').sub(/^[^-]/,' \0') : '')
150
+ end
151
+ end
112
152
  end
113
153
 
114
154
  class RoleSequence
@@ -139,6 +179,7 @@ module ActiveFacts
139
179
 
140
180
  class EntityType
141
181
  def preferred_identifier
182
+ #return @preferred_identifier if @preferred_identifier
142
183
  if fact_type
143
184
 
144
185
  # For a nested fact type, the PI is a unique constraint over N or N-1 roles
@@ -157,10 +198,10 @@ module ActiveFacts
157
198
  if (of = rsr.role.fact_type) != fact_type
158
199
  case of.all_role.size
159
200
  when 1 # A unary FT must be played by the objectification of this fact type
160
- next rsr.role.concept != fact_type.entity_type
201
+ next rsr.role.object_type != fact_type.entity_type
161
202
  when 2 # A binary FT must have the objectification of this FT as the other player
162
203
  other_role = (of.all_role-[rsr.role])[0]
163
- next other_role.concept != fact_type.entity_type
204
+ next other_role.object_type != fact_type.entity_type
164
205
  else
165
206
  next true # A role in a ternary (or higher) cannot be usd in our identifier
166
207
  end
@@ -180,7 +221,7 @@ module ActiveFacts
180
221
  debug :pi, "Got PI #{pi.name||pi.object_id} for nested #{name}" if pi
181
222
  debug :pi, "Looking for PI on entity that nests this fact" unless pi
182
223
  raise "Oops, pi for nested fact is #{pi.class}" unless !pi || pi.is_a?(ActiveFacts::Metamodel::PresenceConstraint)
183
- return pi if pi
224
+ return @preferred_identifier = pi if pi
184
225
  end
185
226
  end
186
227
 
@@ -202,8 +243,8 @@ module ActiveFacts
202
243
  # Note this works with unary fact types:
203
244
  pi_role = ftroles[ftroles[0] != role ? 0 : -1]
204
245
 
205
- next if ftroles.size == 2 && pi_role.concept == self
206
- debug :pi, " Considering #{pi_role.concept.name} as a PI role"
246
+ next if ftroles.size == 2 && pi_role.object_type == self
247
+ debug :pi, " Considering #{pi_role.object_type.name} as a PI role"
207
248
 
208
249
  # If this is an identifying role, the PI is a PC whose role_sequence spans the role.
209
250
  # Walk through all role_sequences that span this role, and test each:
@@ -221,13 +262,13 @@ module ActiveFacts
221
262
  debug :pi, " Role Sequence touches #{fact_type.describe(pi_role)}"
222
263
 
223
264
  fact_type_roles = fact_type.all_role
224
- debug :pi, " residual is #{fact_type_roles.map{|r| r.concept.name}.inspect} minus #{rsr.role.concept.name}"
265
+ debug :pi, " residual is #{fact_type_roles.map{|r| r.object_type.name}.inspect} minus #{rsr.role.object_type.name}"
225
266
  residual_roles = fact_type_roles-[rsr.role]
226
267
  residual_roles.detect{|rfr|
227
- debug :pi, " Checking residual role #{rfr.concept.object_id}=>#{rfr.concept.name}"
268
+ debug :pi, " Checking residual role #{rfr.object_type.object_id}=>#{rfr.object_type.name}"
228
269
  # This next line looks right, but breaks things. Find out what and why:
229
270
  # !rfr.unique or
230
- !all_supertypes.include?(rfr.concept)
271
+ !all_supertypes.include?(rfr.object_type)
231
272
  }
232
273
  }
233
274
  debug :pi, " Discounting this role_sequence because it includes alien roles"
@@ -275,7 +316,7 @@ module ActiveFacts
275
316
  end
276
317
  end
277
318
  raise "No PI found for #{name}" unless pi
278
- pi
319
+ @preferred_identifier = pi
279
320
  end
280
321
  end
281
322
 
@@ -326,8 +367,8 @@ module ActiveFacts
326
367
  def create_implicit_fact_types
327
368
  fact_type.all_role.each do |role|
328
369
  next if role.implicit_fact_type # Already exists
329
- implicit_fact_type = @constellation.ImplicitFactType(:new, :role => role)
330
- phantom_role = @constellation.Role(implicit_fact_type, 0, :concept => self)
370
+ implicit_fact_type = @constellation.ImplicitFactType(:new, :implying_role => role)
371
+ phantom_role = @constellation.Role(implicit_fact_type, 0, :object_type => self)
331
372
  # We could create a copy of the visible external role here, but there's no need yet...
332
373
  # Nor is there a need for a presence constraint, readings, etc.
333
374
  end
@@ -357,7 +398,7 @@ module ActiveFacts
357
398
 
358
399
  expanded.gsub!(/\{#{i}\}/) {
359
400
  role_ref = role_refs[i]
360
- player = role_ref.role.concept
401
+ player = role_ref.role.object_type
361
402
  role_name = role.role_name
362
403
  role_name = nil if role_name == ""
363
404
  if role_name && define_role_names == false
@@ -475,7 +516,7 @@ module ActiveFacts
475
516
  [
476
517
  ((min && min > 0 && min != max) ? "at least #{min == 1 ? "one" : min.to_s}" : nil),
477
518
  ((max && min != max) ? "at most #{max == 1 ? "one" : max.to_s}" : nil),
478
- ((max && min == max) ? "#{max == 1 ? "one" : max.to_s}" : nil)
519
+ ((max && min == max) ? "#{max == 1 ? "one" : "exactly "+max.to_s}" : nil)
479
520
  ].compact * " and "
480
521
  end
481
522
 
@@ -492,11 +533,11 @@ module ActiveFacts
492
533
  end
493
534
 
494
535
  def supertype_role
495
- (roles = all_role.to_a)[0].concept == supertype ? roles[0] : roles[1]
536
+ (roles = all_role.to_a)[0].object_type == supertype ? roles[0] : roles[1]
496
537
  end
497
538
 
498
539
  def subtype_role
499
- (roles = all_role.to_a)[0].concept == subtype ? roles[0] : roles[1]
540
+ (roles = all_role.to_a)[0].object_type == subtype ? roles[0] : roles[1]
500
541
  end
501
542
  end
502
543
 
@@ -507,7 +548,8 @@ module ActiveFacts
507
548
  (is_unary_step ? " (unary) " : "from #{input_join_role.describe} ") +
508
549
  "#{is_anti && 'not '}" +
509
550
  "to #{output_join_role.describe} " +
510
- "over " + (is_objectification_step ? 'objectification ' : '') +
551
+ "over " +
552
+ (is_objectification_step ? 'objectification ' : '') +
511
553
  "'#{fact_type.default_reading}'"
512
554
  end
513
555
 
@@ -531,11 +573,10 @@ module ActiveFacts
531
573
 
532
574
  class JoinNode
533
575
  def describe
534
- concept.name +
576
+ object_type.name +
535
577
  (subscript ? "(#{subscript})" : '') +
536
578
  " JN#{ordinal}" +
537
- # (all_join_role.detect{|jr| jr.role_ref} ? " (projected)" : "") +
538
- (value ? ' = '+value.describe : '')
579
+ (value ? ' = '+value.to_s : '')
539
580
  end
540
581
 
541
582
  def all_join_step
@@ -550,7 +591,7 @@ module ActiveFacts
550
591
 
551
592
  class JoinRole
552
593
  def describe
553
- "#{role.concept.name} JN#{join_node.ordinal}" +
594
+ "#{role.object_type.name} JN#{join_node.ordinal}" +
554
595
  (role_ref ? " (projected)" : "")
555
596
  end
556
597
 
@@ -595,9 +636,9 @@ module ActiveFacts
595
636
  join_nodes = all_join_node.sort_by{|jn| jn.ordinal}
596
637
  join_nodes.each_with_index do |join_node, i|
597
638
  raise "Join node #{i} should have ordinal #{join_node.ordinal}" unless join_node.ordinal == i
598
- raise "Join Node #{i} has missing concept" unless join_node.concept
639
+ raise "Join Node #{i} has missing object_type" unless join_node.object_type
599
640
  join_node.all_join_role do |join_role|
600
- raise "Join Node for #{concept.name} includes role played by #{join_role.concept.name}" unless join_role.concept == concept
641
+ raise "Join Node for #{object_type.name} includes role played by #{join_role.object_type.name}" unless join_role.object_type == object_type
601
642
  end
602
643
  join_steps += join_node.all_join_step
603
644
  end
@@ -622,10 +663,10 @@ module ActiveFacts
622
663
  def default_reading
623
664
  # There are two cases, where role is in a unary fact type, and where the fact type is objectified
624
665
  # If a unary fact type is objectified, only the ImplicitFactType for the objectification is asserted
625
- if objectification = role.fact_type.entity_type
626
- "#{objectification.name} involves #{role.concept.name}"
666
+ if objectification = implying_role.fact_type.entity_type
667
+ "#{objectification.name} involves #{implying_role.object_type.name}"
627
668
  else
628
- role.fact_type.default_reading+" Boolean" # Must be a unary FT
669
+ implying_role.fact_type.default_reading+" Boolean" # Must be a unary FT
629
670
  end
630
671
  end
631
672
 
@@ -651,7 +692,7 @@ module ActiveFacts
651
692
  def leading_adjective; nil; end
652
693
  def trailing_adjective; nil; end
653
694
  def describe
654
- @role.concept.name
695
+ @role.object_type.name
655
696
  end
656
697
  end
657
698
 
@@ -671,16 +712,20 @@ module ActiveFacts
671
712
  end
672
713
 
673
714
  def role_sequence
674
- ImplicitReadingRoleSequence.new([@fact_type.role, @fact_type.all_role.single])
715
+ ImplicitReadingRoleSequence.new([@fact_type.implying_role, @fact_type.all_role.single])
675
716
  end
676
717
 
677
718
  def ordinal; 0; end
719
+
720
+ def expand
721
+ @fact_type.default_reading
722
+ end
678
723
  end
679
724
 
680
725
  def all_reading
681
726
  [@reading ||= ImplicitReading.new(
682
727
  self,
683
- role.fact_type.entity_type ? "{0} involves {1}" : role.fact_type.default_reading+" Boolean"
728
+ implying_role.fact_type.entity_type ? "{0} involves {1}" : implying_role.fact_type.default_reading+" Boolean"
684
729
  )]
685
730
  end
686
731
  end
@@ -694,16 +739,16 @@ module ActiveFacts
694
739
  options != :counterpart && roles.map{|role| role.fact_type}.uniq.size == 1
695
740
  proximate_sups, counterpart_sups, obj_sups, counterpart_roles, objectification_roles =
696
741
  *roles.inject(nil) do |d_c_o, role|
697
- concept = role.concept
742
+ object_type = role.object_type
698
743
  fact_type = role.fact_type
699
744
 
700
- proximate_role_supertypes = concept.supertypes_transitive
745
+ proximate_role_supertypes = object_type.supertypes_transitive
701
746
 
702
747
  # A role in an objectified fact type may indicate either the objectification or the counterpart player.
703
748
  # This could be ambiguous. Figure out both and prefer the counterpart over the objectification.
704
749
  counterpart_role_supertypes =
705
750
  if fact_type.all_role.size > 2
706
- possible_roles = fact_type.all_role.select{|r| d_c_o && d_c_o[1].include?(r.concept) }
751
+ possible_roles = fact_type.all_role.select{|r| d_c_o && d_c_o[1].include?(r.object_type) }
707
752
  if possible_roles.size == 1 # Only one candidate matches the types of the possible join nodes
708
753
  counterpart_role = possible_roles[0]
709
754
  d_c_o[1] # No change
@@ -714,23 +759,23 @@ module ActiveFacts
714
759
  if d_c_o
715
760
  st = nil
716
761
  counterpart_role =
717
- fact_type.all_role.detect{|r| ((st = r.concept.supertypes_transitive) & d_c_o[1]).size > 0}
762
+ fact_type.all_role.detect{|r| ((st = r.object_type.supertypes_transitive) & d_c_o[1]).size > 0}
718
763
  st
719
764
  else
720
765
  counterpart_role = nil # This can't work, we don't have any basis for a decision (must be objectification)
721
766
  []
722
767
  end
723
- #fact_type.all_role.map{|r| r.concept.supertypes_transitive}.flatten.uniq
768
+ #fact_type.all_role.map{|r| r.object_type.supertypes_transitive}.flatten.uniq
724
769
  end
725
770
  else
726
771
  # Get the supertypes of the counterpart role (care with unaries):
727
772
  ftr = role.fact_type.all_role.to_a
728
- (counterpart_role = ftr[0] == role ? ftr[-1] : ftr[0]).concept.supertypes_transitive
773
+ (counterpart_role = ftr[0] == role ? ftr[-1] : ftr[0]).object_type.supertypes_transitive
729
774
  end
730
775
 
731
776
  if fact_type.entity_type
732
777
  objectification_role_supertypes =
733
- fact_type.entity_type.supertypes_transitive+concept.supertypes_transitive
778
+ fact_type.entity_type.supertypes_transitive+object_type.supertypes_transitive
734
779
  objectification_role = role.implicit_fact_type.all_role.single # Find the phantom role here
735
780
  else
736
781
  objectification_role_supertypes = counterpart_role_supertypes
@@ -755,7 +800,7 @@ module ActiveFacts
755
800
  # if we can use an objectification join to an object type that is:
756
801
  if counterpart_sups.size > 0 && obj_sups.size > 0 && counterpart_sups[0] != obj_sups[0]
757
802
  debug :join, "ambiguous join, could be over #{counterpart_sups[0].name} or #{obj_sups[0].name}"
758
- if !roles.detect{|r| r.concept == counterpart_sups[0]} and roles.detect{|r| r.concept == obj_sups[0]}
803
+ if !roles.detect{|r| r.object_type == counterpart_sups[0]} and roles.detect{|r| r.object_type == obj_sups[0]}
759
804
  debug :join, "discounting #{counterpart_sups[0].name} in favour of direct objectification"
760
805
  counterpart_sups = []
761
806
  end
@@ -780,14 +825,14 @@ module ActiveFacts
780
825
  if rv.instance.value
781
826
  v = rv.instance.verbalise
782
827
  else
783
- if (c = rv.instance.concept).is_a?(EntityType)
828
+ if (c = rv.instance.object_type).is_a?(EntityType)
784
829
  if !c.preferred_identifier.role_sequence.all_role_ref.detect{|rr| rr.role.fact_type == fact_type}
785
830
  v = rv.instance.verbalise
786
831
  end
787
832
  end
788
833
  end
789
834
  next nil unless v
790
- v.to_s.sub(/(#{rv.instance.concept.name}|\S*)\s/,'')
835
+ v.to_s.sub(/(#{rv.instance.object_type.name}|\S*)\s/,'')
791
836
  end
792
837
  reading.expand([], false, instance_verbalisations)
793
838
  end
@@ -795,15 +840,15 @@ module ActiveFacts
795
840
 
796
841
  class Instance
797
842
  def verbalise(context = nil)
798
- return "#{concept.name} #{value}" if concept.is_a?(ValueType)
843
+ return "#{object_type.name} #{value}" if object_type.is_a?(ValueType)
799
844
 
800
- return "#{concept.name} where #{fact.verbalise(context)}" if concept.fact_type
845
+ return "#{object_type.name} where #{fact.verbalise(context)}" if object_type.fact_type
801
846
 
802
847
  # It's an entity that's not an objectified fact type
803
848
  # REVISIT: If it has a simple identifier, there's no need to fully verbalise the identifying facts
804
- pi = concept.preferred_identifier
849
+ pi = object_type.preferred_identifier
805
850
  identifying_role_refs = pi.role_sequence.all_role_ref_in_order
806
- "#{concept.name}" +
851
+ "#{object_type.name}" +
807
852
  " is identified by " + # REVISIT: Where the single fact type is TypeInheritance, we can shrink this
808
853
  if identifying_role_refs.size == 1 &&
809
854
  (role = identifying_role_refs[0].role) &&
@@ -816,13 +861,13 @@ module ActiveFacts
816
861
  identifying_role_refs.map do |rr|
817
862
  rr = rr.preferred_role_ref
818
863
  [ (l = rr.leading_adjective) ? l+"-" : nil,
819
- rr.role.role_name || rr.role.concept.name,
864
+ rr.role.role_name || rr.role.object_type.name,
820
865
  (t = rr.trailing_adjective) ? l+"-" : nil
821
866
  ].compact*""
822
867
  end * " and " +
823
868
  " where " +
824
869
  identifying_role_refs.map do |rr| # Go through the identifying roles and emit the facts that define them
825
- instance_role = concept.all_role.detect{|r| r.fact_type == rr.role.fact_type}
870
+ instance_role = object_type.all_role.detect{|r| r.fact_type == rr.role.fact_type}
826
871
  identifying_fact = all_role_value.detect{|rv| rv.fact.fact_type == rr.role.fact_type}.fact
827
872
  #counterpart_role = (rr.role.fact_type.all_role.to_a-[instance_role])[0]
828
873
  #identifying_instance = counterpart_role.all_role_value.detect{|rv| rv.fact == identifying_fact}.instance