activefacts 0.8.18 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +8 -8
  2. data/Rakefile +0 -8
  3. data/examples/CQL/CompanyDirectorEmployee.cql +12 -8
  4. data/examples/CQL/Metamodel.cql +40 -24
  5. data/examples/CQL/OilSupply.cql +10 -8
  6. data/examples/CQL/unit.cql +52 -51
  7. data/lib/activefacts/cql/LexicalRules.treetop +1 -1
  8. data/lib/activefacts/cql/compiler.rb +1 -1
  9. data/lib/activefacts/cql/compiler/clause.rb +16 -24
  10. data/lib/activefacts/cql/compiler/constraint.rb +4 -4
  11. data/lib/activefacts/cql/compiler/entity_type.rb +16 -16
  12. data/lib/activefacts/cql/compiler/expression.rb +3 -3
  13. data/lib/activefacts/cql/compiler/fact.rb +1 -1
  14. data/lib/activefacts/cql/compiler/fact_type.rb +14 -4
  15. data/lib/activefacts/cql/compiler/shared.rb +1 -1
  16. data/lib/activefacts/cql/compiler/value_type.rb +2 -2
  17. data/lib/activefacts/generate/cql.rb +10 -34
  18. data/lib/activefacts/generate/helpers/oo.rb +10 -6
  19. data/lib/activefacts/generate/helpers/ordered.rb +32 -6
  20. data/lib/activefacts/generate/json.rb +2 -2
  21. data/lib/activefacts/generate/ruby.rb +7 -15
  22. data/lib/activefacts/generate/transform/surrogate.rb +7 -7
  23. data/lib/activefacts/input/orm.rb +23 -26
  24. data/lib/activefacts/persistence/index.rb +1 -1
  25. data/lib/activefacts/persistence/reference.rb +5 -2
  26. data/lib/activefacts/version.rb +3 -3
  27. data/lib/activefacts/vocabulary/extensions.rb +59 -19
  28. data/lib/activefacts/vocabulary/metamodel.rb +30 -14
  29. data/spec/cql/parser/bad_literals_spec.rb +1 -1
  30. data/spec/cql/parser/expressions_spec.rb +1 -1
  31. data/spec/cql_dm_spec.rb +15 -0
  32. data/spec/cql_mysql_spec.rb +1 -1
  33. data/spec/cqldump_spec.rb +12 -12
  34. data/spec/norma_cql_spec.rb +0 -1
  35. data/spec/norma_ruby_sql_spec.rb +3 -2
  36. data/spec/norma_tables_spec.rb +1 -1
  37. metadata +78 -127
  38. data/examples/CQL/JoinEquality.cql +0 -35
  39. data/examples/CQL/MonthInSeason.cql +0 -23
  40. data/examples/CQL/Moon.cql +0 -23
  41. data/examples/CQL/SubtypePI.cql +0 -31
  42. data/examples/CQL/Tests.Test5.Load.cql +0 -38
@@ -158,7 +158,7 @@ module ActiveFacts
158
158
  end
159
159
 
160
160
  rule alpha
161
- [[:alpha:]]
161
+ [[:alpha:]_]
162
162
  end
163
163
 
164
164
  rule alphanumeric
@@ -96,7 +96,7 @@ module ActiveFacts
96
96
  saved_string = @string
97
97
  saved_input_length = @input_length
98
98
  old_filename = @filename
99
- @filename = file+'.cql' # REVISIT: Use File.dirname(@filename)+@filename ?
99
+ @filename = File.dirname(old_filename)+'/'+file+'.cql'
100
100
 
101
101
  # REVISIT: Save and use another @vocabulary for this file?
102
102
  File.open(@filename) do |f|
@@ -232,26 +232,13 @@ module ActiveFacts
232
232
  candidate_fact_types =
233
233
  start_obj.map do |related_type|
234
234
  related_type.all_role.select do |role|
235
- all_roles = role.fact_type.all_role
236
- next if all_roles.size != players.size # Wrong number of players
235
+ # next if role.fact_type.all_reading.size == 0
237
236
  next if role.fact_type.is_a?(ActiveFacts::Metamodel::LinkFactType)
237
+ next if role.fact_type.all_role.size != players.size # Wrong number of players
238
238
 
239
- all_players = all_roles.map{|r| r.object_type} # All the players of this candidate fact type
240
-
241
- next if player_related_types[1..-1]. # We know the first player is compatible, check the rest
242
- detect do |player_types| # Make sure that there remains a compatible player
243
- # player_types is an array of the types compatible with the Nth player
244
- compatible_player = nil
245
- all_players.each_with_index do |p, i|
246
- if player_types.include?(p)
247
- compatible_player = p
248
- all_players.delete_at(i)
249
- break
250
- end
251
- end
252
- !compatible_player
253
- end
254
-
239
+ compatible_readings = role.fact_type.compatible_readings(player_related_types)
240
+ next unless compatible_readings.size > 0
241
+ debug :matching_fails, "These readings are compatible: #{compatible_readings.map(&:expand).inspect}"
255
242
  true
256
243
  end.
257
244
  map{ |role| role.fact_type}
@@ -419,9 +406,14 @@ module ActiveFacts
419
406
  if la = role_ref.leading_adjective and !la.empty?
420
407
  # The leading adjectives must match, one way or another
421
408
  la = la.split(/\s+/)
422
- # We may have hyphenated adjectives. Break them up to check:
423
- iw = intervening_words.map{|w| w.split(/-/)}.flatten
424
- return nil unless la[0,iw.size] == iw
409
+ if (la[0, intervening_words.size] == intervening_words) # Exact match
410
+ iw = intervening_words
411
+ else
412
+ # We may have hyphenated adjectives. Break them up to check:
413
+ iw = intervening_words.map{|w| w.split(/-/)}.flatten
414
+ return nil unless la[0,iw.size] == iw
415
+ end
416
+
425
417
  # Any intervening_words matched, see what remains
426
418
  la.slice!(0, iw.size)
427
419
 
@@ -593,7 +585,7 @@ module ActiveFacts
593
585
  debug :matching, "Making new fact type for #{@phrases.inspect}" do
594
586
  @phrases.each do |phrase|
595
587
  next unless phrase.respond_to?(:player)
596
- phrase.role = vocabulary.constellation.Role(fact_type, fact_type.all_role.size, :object_type => phrase.player, :guid => :new)
588
+ phrase.role = vocabulary.constellation.Role(fact_type, fact_type.all_role.size, :object_type => phrase.player, :concept => :new)
597
589
  phrase.role.role_name = phrase.role_name if phrase.role_name && phrase.role_name.is_a?(String)
598
590
  end
599
591
  end
@@ -801,7 +793,7 @@ module ActiveFacts
801
793
  @negated = negated
802
794
  end
803
795
 
804
- def to_s
796
+ def inspect
805
797
  'side-effects are [' +
806
798
  @role_side_effects.map{|r| r.to_s}*', ' +
807
799
  ']' +
@@ -1035,7 +1027,7 @@ module ActiveFacts
1035
1027
  :max_frequency => @quantifier.max,
1036
1028
  :min_frequency => @quantifier.min
1037
1029
  )
1038
- debug :constraint, "Made new embedded PC GUID=#{constraint.guid} min=#{@quantifier.min.inspect} max=#{@quantifier.max.inspect} over #{(e = fact_type.entity_type) ? e.name : role_sequence.describe} in #{fact_type.describe}"
1030
+ debug :constraint, "Made new embedded PC GUID=#{constraint.concept.guid} min=#{@quantifier.min.inspect} max=#{@quantifier.max.inspect} over #{(e = fact_type.entity_type) ? e.name : role_sequence.describe} in #{fact_type.describe}"
1039
1031
  @quantifier.enforcement.compile(constellation, constraint) if @quantifier.enforcement
1040
1032
  @embedded_presence_constraint = constraint
1041
1033
  end
@@ -28,7 +28,7 @@ module ActiveFacts
28
28
  :context_note_kind => @context_kind,
29
29
  :discussion => @discussion
30
30
  )
31
- context_note.relevant_concept = target
31
+ context_note.relevant_concept = target.concept
32
32
  if @agreed_date || @agreed_agents
33
33
  agreement = constellation.Agreement(context_note)
34
34
  agreement.date = @agreed_date if @agreed_date
@@ -226,7 +226,7 @@ module ActiveFacts
226
226
  :is_mandatory => @quantifier.min && @quantifier.min > 0
227
227
  )
228
228
  @enforcement.compile(@constellation, @constraint) if @enforcement
229
- debug :constraint, "Made new PC GUID=#{@constraint.guid} min=#{@quantifier.min.inspect} max=#{@quantifier.max.inspect} over #{role_sequence.describe}"
229
+ debug :constraint, "Made new PC GUID=#{@constraint.concept.guid} min=#{@quantifier.min.inspect} max=#{@quantifier.max.inspect} over #{role_sequence.describe}"
230
230
  super
231
231
  end
232
232
 
@@ -461,7 +461,7 @@ module ActiveFacts
461
461
  raise "ambiguous #{@rings*' '} ring constraint, consider #{role_pairs.map{|rp| "#{rp[0].inspect}<->#{rp[1].inspect}"}*', '}"
462
462
  end
463
463
  if role_pairs.size == 0
464
- raise "No matching role pair found for #{@rings*' '} ring constraint"
464
+ raise "No matching role pair found for #{@rings*' '} ring constraint over #{role_refs.map(&:role).map(&:object_type).map(&:name).inspect}"
465
465
  end
466
466
 
467
467
  rp = role_pairs[0]
@@ -483,7 +483,7 @@ module ActiveFacts
483
483
  :ring_type => ring_type
484
484
  )
485
485
 
486
- debug :constraint, "Added #{@constraint.verbalise} #{@constraint.class.roles.keys.map{|k|"#{k} => "+@constraint.send(k).verbalise}*", "}"
486
+ debug :constraint, "Added #{@constraint.verbalise}"
487
487
  super
488
488
  end
489
489
 
@@ -30,7 +30,7 @@ module ActiveFacts
30
30
 
31
31
  def compile
32
32
  @entity_type = @vocabulary.valid_entity_type_name(@name) ||
33
- @constellation.EntityType(@vocabulary, @name, :guid => :new)
33
+ @constellation.EntityType(@vocabulary, @name, :concept => :new)
34
34
  @entity_type.is_independent = true if (@pragmas.include? 'independent')
35
35
 
36
36
  # REVISIT: CQL needs a way to indicate whether subtype migration can occur.
@@ -122,7 +122,7 @@ module ActiveFacts
122
122
  if (pc)
123
123
  pc.is_preferred_identifier = true
124
124
  pc.name = "#{@entity_type.name}PK" unless pc.name
125
- debug "Existing PC #{pc.verbalise} is now PK for #{@entity_type.name} #{pc.class.roles.keys.map{|k|"#{k} => "+pc.send(k).verbalise}*", "}"
125
+ debug "Existing PC #{pc.verbalise} is now PK for #{@entity_type.name}"
126
126
  else
127
127
  # Add a unique constraint over all identifying roles
128
128
  pc = @constellation.PresenceConstraint(
@@ -135,7 +135,7 @@ module ActiveFacts
135
135
  #:is_mandatory => true,
136
136
  #:min_frequency => 1,
137
137
  )
138
- debug :constraint, "Made new preferred PC GUID=#{pc.guid} min=nil max=1 over #{role_sequence.describe}"
138
+ debug :constraint, "Made new preferred PC GUID=#{pc.concept.guid} min=nil max=1 over #{role_sequence.describe}"
139
139
  end
140
140
  end
141
141
 
@@ -220,7 +220,7 @@ module ActiveFacts
220
220
  :is_preferred_identifier => false, # We only get here when there is a reference mode on the entity type
221
221
  :max_frequency => 1
222
222
  )
223
- debug :constraint, "Made new objectification PC GUID=#{pc.guid} min=nil max=1 over #{fact_type.preferred_reading.role_sequence.describe}"
223
+ debug :constraint, "Made new objectification PC GUID=#{pc.concept.guid} min=nil max=1 over #{fact_type.preferred_reading.role_sequence.describe}"
224
224
  end
225
225
 
226
226
  @fact_type = @entity_type.fact_type = fact_type
@@ -231,7 +231,7 @@ module ActiveFacts
231
231
  def add_supertype(supertype_name, not_identifying)
232
232
  debug :supertype, "Adding #{not_identifying ? '' : 'identifying '}supertype #{supertype_name} to #{@entity_type.name}" do
233
233
  supertype = @vocabulary.valid_entity_type_name(supertype_name) ||
234
- @constellation.EntityType(@vocabulary, supertype_name, :guid => :new) # Should always already exist
234
+ @constellation.EntityType(@vocabulary, supertype_name, :concept => :new) # Should always already exist
235
235
 
236
236
  # Did we already know about this supertyping?
237
237
  return if @entity_type.all_type_inheritance_as_subtype.detect{|ti| ti.supertype == supertype}
@@ -239,15 +239,15 @@ module ActiveFacts
239
239
  # By default, the first supertype identifies this entity type
240
240
  is_identifying_supertype = !not_identifying && @entity_type.all_type_inheritance_as_subtype.size == 0
241
241
 
242
- inheritance_fact = @constellation.TypeInheritance(@entity_type, supertype, :guid => :new)
242
+ inheritance_fact = @constellation.TypeInheritance(@entity_type, supertype, :concept => :new)
243
243
 
244
244
  assimilations = @pragmas.select { |p| ['absorbed', 'separate', 'partitioned'].include? p}
245
245
  raise "Conflicting assimilation pragmas #{assimilations*', '}" if assimilations.size > 1
246
246
  inheritance_fact.assimilation = assimilations[0]
247
247
 
248
248
  # Create a reading:
249
- sub_role = @constellation.Role(inheritance_fact, 0, :object_type => @entity_type, :guid => :new)
250
- super_role = @constellation.Role(inheritance_fact, 1, :object_type => supertype, :guid => :new)
249
+ sub_role = @constellation.Role(inheritance_fact, 0, :object_type => @entity_type, :concept => :new)
250
+ super_role = @constellation.Role(inheritance_fact, 1, :object_type => supertype, :concept => :new)
251
251
 
252
252
  rs = @constellation.RoleSequence(:new)
253
253
  @constellation.RoleRef(rs, 0, :role => sub_role)
@@ -275,7 +275,7 @@ module ActiveFacts
275
275
  pc1.min_frequency = 1
276
276
  pc1.max_frequency = 1
277
277
  pc1.is_preferred_identifier = false
278
- debug :constraint, "Made new subtype PC GUID=#{pc1.guid} min=1 max=1 over #{p1rs.describe}"
278
+ debug :constraint, "Made new subtype PC GUID=#{pc1.concept.guid} min=1 max=1 over #{p1rs.describe}"
279
279
 
280
280
  p2rs = @constellation.RoleSequence(:new)
281
281
  constellation.RoleRef(p2rs, 0).role = super_role
@@ -288,7 +288,7 @@ module ActiveFacts
288
288
  # The supertype role often identifies the subtype:
289
289
  pc2.is_preferred_identifier = inheritance_fact.provides_identification
290
290
  debug :supertype, "identification of #{@entity_type.name} via supertype #{supertype.name} was #{inheritance_fact.provides_identification ? '' : 'not '}added"
291
- debug :constraint, "Made new supertype PC GUID=#{pc2.guid} min=1 max=1 over #{p2rs.describe}"
291
+ debug :constraint, "Made new supertype PC GUID=#{pc2.concept.guid} min=1 max=1 over #{p2rs.describe}"
292
292
  end
293
293
  end
294
294
 
@@ -301,8 +301,8 @@ module ActiveFacts
301
301
  unless vt = @vocabulary.valid_object_type_name(vt_name) or
302
302
  vt = @vocabulary.valid_object_type_name(vt_name = "#{name} #{mode}")
303
303
  base_vt = @vocabulary.valid_value_type_name(mode) ||
304
- @constellation.ValueType(@vocabulary, mode, :guid => :new)
305
- vt = @constellation.ValueType(@vocabulary, vt_name, :supertype => base_vt, :guid => :new)
304
+ @constellation.ValueType(@vocabulary, mode, :concept => :new)
305
+ vt = @constellation.ValueType(@vocabulary, vt_name, :supertype => base_vt, :concept => :new)
306
306
  if parameters
307
307
  length, scale = *parameters
308
308
  vt.length = length if length
@@ -335,8 +335,8 @@ module ActiveFacts
335
335
  unless fact_type
336
336
  fact_type = @constellation.FactType(:new)
337
337
  fact_types << fact_type
338
- entity_role = @constellation.Role(fact_type, 0, :object_type => @entity_type, :guid => :new)
339
- identifying_role = @constellation.Role(fact_type, 1, :object_type => identifying_type, :guid => :new)
338
+ entity_role = @constellation.Role(fact_type, 0, :object_type => @entity_type, :concept => :new)
339
+ identifying_role = @constellation.Role(fact_type, 1, :object_type => identifying_type, :concept => :new)
340
340
  end
341
341
  @identification[0].role = identifying_role
342
342
 
@@ -403,7 +403,7 @@ module ActiveFacts
403
403
  :is_preferred_identifier => false,
404
404
  :is_mandatory => true
405
405
  )
406
- debug :constraint, "Made new refmode PC GUID=#{constraint.guid} min=1 max=1 over #{rs0.describe}"
406
+ debug :constraint, "Made new refmode PC GUID=#{constraint.concept.guid} min=1 max=1 over #{rs0.describe}"
407
407
  else
408
408
  debug :mode, "Using existing EntityType PresenceConstraint"
409
409
  end
@@ -431,7 +431,7 @@ module ActiveFacts
431
431
  :is_preferred_identifier => true,
432
432
  :is_mandatory => false
433
433
  )
434
- debug :constraint, "Made new refmode ValueType PC GUID=#{constraint.guid} min=0 max=1 over #{rs1.describe}"
434
+ debug :constraint, "Made new refmode ValueType PC GUID=#{constraint.concept.guid} min=0 max=1 over #{rs1.describe}"
435
435
  else
436
436
  debug :mode, "Marking existing ValueType PresenceConstraint as preferred"
437
437
  rs1.all_presence_constraint.single.is_preferred_identifier = true
@@ -93,7 +93,7 @@ module ActiveFacts
93
93
  vocabulary = context.vocabulary
94
94
  constellation = vocabulary.constellation
95
95
  vocabulary.valid_value_type_name(name) ||
96
- constellation.ValueType(vocabulary, name, :guid => :new)
96
+ constellation.ValueType(vocabulary, name, :concept => :new)
97
97
  end
98
98
 
99
99
  def is_naked_object_type
@@ -194,7 +194,7 @@ module ActiveFacts
194
194
  v = context.vocabulary
195
195
  @boolean ||=
196
196
  v.constellation.ValueType[[[v.name], 'Boolean']] ||
197
- v.constellation.ValueType(v, 'Boolean', :guid => :new)
197
+ v.constellation.ValueType(v, 'Boolean', :concept => :new)
198
198
  @player = @boolean
199
199
  end
200
200
  end
@@ -337,7 +337,7 @@ module ActiveFacts
337
337
  # REVISIT: Calculate the units of the result from the units in @divisor
338
338
  # REVISIT: Do we want integer division?
339
339
  v = context.vocabulary
340
- @player = v.constellation.ValueType(v, 'Real', :guid => :new)
340
+ @player = v.constellation.ValueType(v, 'Real', :concept => :new)
341
341
  end
342
342
  end
343
343
 
@@ -10,7 +10,7 @@ module ActiveFacts
10
10
 
11
11
  def compile
12
12
  @population = @constellation.Population[[@vocabulary.identifying_role_values, @population_name]] ||
13
- @constellation.Population(@vocabulary, @population_name, :guid => :new)
13
+ @constellation.Population(@vocabulary, @population_name, :concept => :new)
14
14
 
15
15
  @context = CompilationContext.new(@vocabulary)
16
16
  @context.bind @clauses
@@ -97,7 +97,7 @@ module ActiveFacts
97
97
  if @name
98
98
  entity_type = @vocabulary.valid_entity_type_name(@name)
99
99
  raise "You can't objectify #{@name}, it already exists" if entity_type
100
- @entity_type = @constellation.EntityType(@vocabulary, @name, :fact_type => @fact_type, :guid => :new)
100
+ @entity_type = @constellation.EntityType(@vocabulary, @name, :fact_type => @fact_type, :concept => :new)
101
101
  end
102
102
 
103
103
  prepare_roles @clauses
@@ -286,15 +286,23 @@ module ActiveFacts
286
286
  debug :constraint, "Need to check #{@fact_type.default_reading.inspect} for a uniqueness constraint"
287
287
  fact_type.check_and_add_spanning_uniqueness_constraint = proc do
288
288
  debug :constraint, "Checking #{@fact_type.default_reading.inspect} for a uniqueness constraint"
289
- if !@fact_type.all_role.
289
+ existing_pc = nil
290
+ found = @fact_type.all_role.
290
291
  detect do |role|
291
292
  role.all_role_ref.detect do |rr|
292
293
  # This RoleSequence, to be relevant, must only reference roles of this fact type
293
294
  rr.role_sequence.all_role_ref.all? {|rr2| rr2.role.fact_type == @fact_type} and
294
295
  # The RoleSequence must have at least one uniqueness constraint
295
- rr.role_sequence.all_presence_constraint.detect{|pc| pc.max_frequency == 1}
296
+ rr.role_sequence.all_presence_constraint.detect do |pc|
297
+ if pc.max_frequency == 1
298
+ existing_pc = pc
299
+ end
300
+ end
296
301
  end
297
302
  end
303
+ true # A place for a breakpoint
304
+
305
+ if !found
298
306
  # There's no existing uniqueness constraint over the roles of this fact type. Add one
299
307
  pc = @constellation.PresenceConstraint(
300
308
  :new,
@@ -304,7 +312,9 @@ module ActiveFacts
304
312
  :max_frequency => 1,
305
313
  :is_preferred_identifier => true # (prefer || !!@fact_type.entity_type)
306
314
  )
307
- debug :constraint, "Made new fact type implicit PC GUID=#{pc.guid} #{pc.name} min=nil max=1 over #{rs.describe}"
315
+ debug :constraint, "Made new fact type implicit PC GUID=#{pc.concept.guid} #{pc.name} min=nil max=1 over #{rs.describe}"
316
+ elsif pc
317
+ debug :constraint, "Will rely on existing UC GUID=#{pc.concept.guid} #{pc.name} to be used as PI over #{rs.describe}"
308
318
  end
309
319
  end
310
320
  end
@@ -65,7 +65,7 @@ module ActiveFacts
65
65
 
66
66
  if !player && @allowed_forward_terms.include?(name)
67
67
  @vocabulary.valid_entity_type_name(name) # No need for the result here, just no exceptional condition
68
- player = constellation.EntityType(@vocabulary, name, :guid => :new)
68
+ player = constellation.EntityType(@vocabulary, name, :concept => :new)
69
69
  end
70
70
 
71
71
  player
@@ -104,14 +104,14 @@ module ActiveFacts
104
104
  base_type = nil
105
105
  if (@base_type_name != @name)
106
106
  unless base_type = @vocabulary.valid_value_type_name(@base_type_name)
107
- base_type = @constellation.ValueType(@vocabulary, @base_type_name, :guid => :new)
107
+ base_type = @constellation.ValueType(@vocabulary, @base_type_name, :concept => :new)
108
108
  return base_type if @base_type_name == @name
109
109
  end
110
110
  end
111
111
 
112
112
  # Create and initialise the ValueType:
113
113
  vt = @vocabulary.valid_value_type_name(@name) ||
114
- @constellation.ValueType(@vocabulary, @name, :guid => :new)
114
+ @constellation.ValueType(@vocabulary, @name, :concept => :new)
115
115
  vt.is_independent = true if (@pragmas.include? 'independent')
116
116
  vt.supertype = base_type if base_type
117
117
  vt.length = length if length
@@ -42,40 +42,15 @@ module ActiveFacts
42
42
  puts "\n"
43
43
  end
44
44
 
45
- def value_type_dump(o)
46
- # Ignore Value Types that don't do anything:
47
- return if
48
- !o.supertype &&
49
- o.all_role.size == 0 &&
50
- !o.is_independent &&
51
- !o.value_constraint &&
52
- o.all_context_note_as_relevant_concept.size == 0 &&
53
- o.all_instance.size == 0
45
+ def data_type_dump(o)
46
+ value_type_dump(o, o.name, {}) if o.all_role.size > 0
47
+ end
48
+
49
+ def value_type_dump(o, super_type_name, facets)
54
50
  # No need to dump it if the only thing it does is be a supertype; it'll be created automatically
55
51
  # return if o.all_value_type_as_supertype.size == 0
56
52
 
57
- =begin
58
- # Leave this out, pending a proper on-demand system for dumping VT's
59
- # A ValueType that is only used as a reference mode need not be emitted here.
60
- if o.all_value_type_as_supertype.size == 0 &&
61
- !o.all_role.
62
- detect do |role|
63
- (other_roles = role.fact_type.all_role.to_a-[role]).size != 1 || # Not a role in a binary FT
64
- !(object_type = other_roles[0].object_type).is_a?(ActiveFacts::Metamodel::EntityType) || # Counterpart is not an ET
65
- (pi = object_type.preferred_identifier).role_sequence.all_role_ref.size != 1 || # Entity PI has > 1 roles
66
- pi.role_sequence.all_role_ref.single.role != role # This isn't the identifying role
67
- end
68
- puts "About to skip #{o.name}"
69
- debugger
70
- return
71
- end
72
-
73
- # We'll dump the subtypes before any roles, so we don't need to dump this here.
74
- # ... except that isn't true, we won't do that so we can't skip it now
75
- #return if
76
- # o.all_value_type_as_supertype.size != 0 && # We have subtypes
77
- # o.all_role.size != 0
78
- =end
53
+ # REVISIT: A ValueType that is only used as a reference mode need not be emitted here.
79
54
 
80
55
  puts o.as_cql
81
56
  end
@@ -216,7 +191,7 @@ module ActiveFacts
216
191
  end
217
192
  (entity_type.is_independent ? ' independent' : '') +
218
193
  " identified by its #{value_residual}#{constraint_text}#{mapping_pragma(entity_type, true)}" +
219
- entity_type.all_context_note_as_relevant_concept.map do |cn|
194
+ entity_type.concept.all_context_note_as_relevant_concept.map do |cn|
220
195
  cn.verbalise
221
196
  end.join("\n") +
222
197
  (fact_readings.size > 0 ? " where\n\t" : "") +
@@ -253,7 +228,7 @@ module ActiveFacts
253
228
  (entity_type.is_independent ? ' independent' : '') +
254
229
  " identified by #{ irn*" and " }" +
255
230
  mapping_pragma(entity_type, true) +
256
- entity_type.all_context_note_as_relevant_concept.map do |cn|
231
+ entity_type.concept.all_context_note_as_relevant_concept.map do |cn|
257
232
  cn.verbalise
258
233
  end.join("\n") +
259
234
  " where\n\t"+identifying_fact_text
@@ -656,7 +631,7 @@ module ActiveFacts
656
631
  }#{
657
632
  unit && " "+unit.name
658
633
  }#{
659
- all_context_note_as_relevant_concept.map do |cn|
634
+ concept.all_context_note_as_relevant_concept.map do |cn|
660
635
  cn.verbalise
661
636
  end.join("\n")
662
637
  }#{
@@ -687,6 +662,7 @@ module ActiveFacts
687
662
  end +
688
663
 
689
664
  all_derivation_as_derived_unit.
665
+ sort_by{|d| d.base_unit.name}.
690
666
  # REVISIT: Sort base units
691
667
  # REVISIT: convert negative powers to division?
692
668
  map do |der|
@@ -97,11 +97,12 @@ module ActiveFacts
97
97
  binary_dump(role, other_role_name, other_player, role.is_mandatory, one_to_one, nil, role_name, other_role_method)
98
98
  end
99
99
 
100
- def preferred_role_name(role, is_for = nil)
101
- return "" if role.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
100
+ def preferred_role_name(role, is_for = nil, &b)
101
+ b ||= proc {|names| names.map(&:downcase)*'_' } # Make snake_case by default
102
+ return b.call([]) if role.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
102
103
 
103
104
  if is_for && role.fact_type.entity_type == is_for && role.fact_type.all_role.size == 1
104
- return role.object_type.name.gsub(/[- ]/,'_').snakecase
105
+ return b.call(role.object_type.name.gsub(/[- ]/,'_').split(/_/))
105
106
  end
106
107
 
107
108
  # debug "Looking for preferred_role_name of #{describe_fact_type(role.fact_type, role)}"
@@ -112,8 +113,11 @@ module ActiveFacts
112
113
 
113
114
  # Unaries are a hack, with only one role for what is effectively a binary:
114
115
  if (role.fact_type.all_role.size == 1)
115
- return (role.role_name && role.role_name.snakecase) ||
116
- reading.text.gsub(/ *\{0\} */,'').gsub(/[- ]/,'_').downcase
116
+ return b.call(
117
+ ( (role.role_name && role.role_name.snakecase) ||
118
+ reading.text.gsub(/ *\{0\} */,'').gsub(/[- ]/,'_')
119
+ ).split(/_/)
120
+ )
117
121
  end
118
122
 
119
123
  # debug "\tleading_adjective=#{(p=preferred_role_ref).leading_adjective}, role_name=#{role.role_name}, role player=#{role.object_type.name}, trailing_adjective=#{p.trailing_adjective}"
@@ -131,7 +135,7 @@ module ActiveFacts
131
135
  role_words << ta.gsub(/[- ]/,'_') if ta && ta != "" and !role_name
132
136
  n = role_words.map{|w| w.gsub(/([a-z])([A-Z]+)/,'\1_\2').downcase}*"_"
133
137
  # debug "\tresult=#{n}"
134
- n.gsub(' ','_')
138
+ return b.call(n.gsub(' ','_').split(/_/))
135
139
  end
136
140
 
137
141
  def skip_fact_type(f)