activefacts 0.8.6 → 0.8.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) hide show
  1. data/Manifest.txt +33 -2
  2. data/README.rdoc +30 -36
  3. data/Rakefile +16 -20
  4. data/bin/afgen +17 -11
  5. data/bin/cql +313 -36
  6. data/download.html +43 -19
  7. data/examples/CQL/Address.cql +15 -15
  8. data/examples/CQL/Blog.cql +8 -8
  9. data/examples/CQL/CompanyDirectorEmployee.cql +6 -5
  10. data/examples/CQL/Death.cql +3 -3
  11. data/examples/CQL/Diplomacy.cql +48 -0
  12. data/examples/CQL/Genealogy.cql +41 -41
  13. data/examples/CQL/Insurance.cql +311 -0
  14. data/examples/CQL/JoinEquality.cql +35 -0
  15. data/examples/CQL/Marriage.cql +1 -1
  16. data/examples/CQL/Metamodel.cql +290 -185
  17. data/examples/CQL/MetamodelNext.cql +420 -0
  18. data/examples/CQL/Monogamy.cql +24 -0
  19. data/examples/CQL/MonthInSeason.cql +27 -0
  20. data/examples/CQL/Moon.cql +23 -0
  21. data/examples/CQL/MultiInheritance.cql +4 -4
  22. data/examples/CQL/NonRoleId.cql +14 -0
  23. data/examples/CQL/OddIdentifier.cql +18 -0
  24. data/examples/CQL/OilSupply.cql +24 -24
  25. data/examples/CQL/OneToOnes.cql +17 -0
  26. data/examples/CQL/Orienteering.cql +55 -55
  27. data/examples/CQL/OrienteeringER.cql +58 -0
  28. data/examples/CQL/PersonPlaysGame.cql +2 -2
  29. data/examples/CQL/RedundantDependency.cql +34 -0
  30. data/examples/CQL/SchoolActivities.cql +5 -5
  31. data/examples/CQL/SeparateSubtype.cql +28 -0
  32. data/examples/CQL/ServiceDirector.cql +283 -0
  33. data/examples/CQL/SimplestUnary.cql +2 -2
  34. data/examples/CQL/SubtypePI.cql +11 -11
  35. data/examples/CQL/Supervision.cql +38 -0
  36. data/examples/CQL/Tests.Test5.Load.cql +38 -0
  37. data/examples/CQL/WaiterTips.cql +33 -0
  38. data/examples/CQL/Warehousing.cql +55 -53
  39. data/examples/CQL/WindowInRoomInBldg.cql +9 -9
  40. data/examples/CQL/unit.cql +433 -544
  41. data/examples/index.html +314 -170
  42. data/examples/intro.html +6 -176
  43. data/examples/local.css +8 -4
  44. data/index.html +40 -25
  45. data/lib/activefacts/api/concept.rb +2 -2
  46. data/lib/activefacts/api/constellation.rb +4 -4
  47. data/lib/activefacts/api/instance.rb +2 -2
  48. data/lib/activefacts/api/instance_index.rb +4 -0
  49. data/lib/activefacts/api/numeric.rb +3 -1
  50. data/lib/activefacts/api/role.rb +1 -1
  51. data/lib/activefacts/api/standard_types.rb +23 -16
  52. data/lib/activefacts/api/support.rb +3 -1
  53. data/lib/activefacts/api/vocabulary.rb +4 -0
  54. data/lib/activefacts/cql/CQLParser.treetop +87 -39
  55. data/lib/activefacts/cql/Concepts.treetop +95 -69
  56. data/lib/activefacts/cql/Context.treetop +11 -2
  57. data/lib/activefacts/cql/Expressions.treetop +23 -59
  58. data/lib/activefacts/cql/FactTypes.treetop +141 -95
  59. data/lib/activefacts/cql/Language/English.treetop +33 -21
  60. data/lib/activefacts/cql/LexicalRules.treetop +6 -1
  61. data/lib/activefacts/cql/Terms.treetop +75 -26
  62. data/lib/activefacts/cql/ValueTypes.treetop +52 -54
  63. data/lib/activefacts/cql/compiler.rb +46 -1691
  64. data/lib/activefacts/cql/compiler/constraint.rb +602 -0
  65. data/lib/activefacts/cql/compiler/entity_type.rb +425 -0
  66. data/lib/activefacts/cql/compiler/fact.rb +300 -0
  67. data/lib/activefacts/cql/compiler/fact_type.rb +230 -0
  68. data/lib/activefacts/cql/compiler/reading.rb +832 -0
  69. data/lib/activefacts/cql/compiler/shared.rb +109 -0
  70. data/lib/activefacts/cql/compiler/value_type.rb +104 -0
  71. data/lib/activefacts/cql/parser.rb +132 -81
  72. data/lib/activefacts/generate/cql.rb +397 -274
  73. data/lib/activefacts/generate/oo.rb +13 -12
  74. data/lib/activefacts/generate/ordered.rb +107 -117
  75. data/lib/activefacts/generate/ruby.rb +34 -38
  76. data/lib/activefacts/generate/sql/mysql.rb +62 -45
  77. data/lib/activefacts/generate/sql/server.rb +59 -42
  78. data/lib/activefacts/input/cql.rb +6 -3
  79. data/lib/activefacts/input/orm.rb +991 -557
  80. data/lib/activefacts/persistence/columns.rb +16 -12
  81. data/lib/activefacts/persistence/foreignkey.rb +7 -4
  82. data/lib/activefacts/persistence/index.rb +3 -4
  83. data/lib/activefacts/persistence/reference.rb +5 -2
  84. data/lib/activefacts/support.rb +20 -14
  85. data/lib/activefacts/version.rb +1 -1
  86. data/lib/activefacts/vocabulary.rb +1 -0
  87. data/lib/activefacts/vocabulary/extensions.rb +328 -44
  88. data/lib/activefacts/vocabulary/metamodel.rb +145 -20
  89. data/lib/activefacts/vocabulary/verbaliser.rb +621 -0
  90. data/spec/absorption_spec.rb +4 -4
  91. data/spec/api/value_type.rb +1 -1
  92. data/spec/cql/context_spec.rb +45 -22
  93. data/spec/cql/deontic_spec.rb +88 -0
  94. data/spec/cql/matching_spec.rb +517 -0
  95. data/spec/cql/samples_spec.rb +88 -31
  96. data/spec/cql/unit_spec.rb +58 -37
  97. data/spec/cql_cql_spec.rb +12 -7
  98. data/spec/cql_mysql_spec.rb +3 -7
  99. data/spec/cql_parse_spec.rb +0 -4
  100. data/spec/cql_ruby_spec.rb +1 -4
  101. data/spec/cql_sql_spec.rb +5 -18
  102. data/spec/cql_symbol_tables_spec.rb +3 -0
  103. data/spec/cqldump_spec.rb +0 -2
  104. data/spec/helpers/array_matcher.rb +35 -0
  105. data/spec/helpers/ctrl_c_support.rb +52 -0
  106. data/spec/helpers/diff_matcher.rb +38 -0
  107. data/spec/helpers/file_matcher.rb +5 -3
  108. data/spec/helpers/string_matcher.rb +39 -0
  109. data/spec/helpers/test_parser.rb +13 -0
  110. data/spec/norma_cql_spec.rb +13 -5
  111. data/spec/norma_ruby_spec.rb +11 -3
  112. data/spec/{absorption_ruby_spec.rb → norma_ruby_sql_spec.rb} +37 -32
  113. data/spec/norma_sql_spec.rb +11 -5
  114. data/spec/norma_tables_spec.rb +33 -29
  115. data/spec/spec_helper.rb +4 -1
  116. data/status.html +92 -23
  117. metadata +102 -36
  118. data/lib/activefacts/generate/cql/html.rb +0 -403
@@ -24,7 +24,8 @@ module ActiveFacts
24
24
  def roles_dump(o)
25
25
  o.all_role.
26
26
  select{|role|
27
- role.fact_type.all_role.size <= 2
27
+ role.fact_type.all_role.size <= 2 &&
28
+ !role.fact_type.is_a?(ActiveFacts::Metamodel::ImplicitFactType)
28
29
  }.
29
30
  sort_by{|role|
30
31
  preferred_role_name(role.fact_type.all_role.select{|r2| r2 != role}[0] || role, o)
@@ -68,8 +69,8 @@ module ActiveFacts
68
69
  other_player = fact_type.entity_type
69
70
  return unless @concept_types_dumped[other_player]
70
71
 
71
- other_role_name = other_player.name.snakecase
72
- other_role_method = role.concept.name.snakecase
72
+ other_role_name = other_player.name.gsub(/ /,'_').snakecase
73
+ other_role_method = role.concept.name.gsub(/ /,'_').snakecase
73
74
  one_to_one = true
74
75
  else
75
76
 
@@ -89,14 +90,14 @@ module ActiveFacts
89
90
  role_method = preferred_role_name(role)
90
91
  other_role_method = one_to_one ? role_method : "all_"+role_method
91
92
  # puts "---"+role.role_name if role.role_name
92
- if other_role_name != other_player.name.snakecase and
93
- role_method == role.concept.name.snakecase
93
+ if other_role_name != other_player.name.gsub(/ /,'_').snakecase and
94
+ role_method == role.concept.name.gsub(/ /,'_').snakecase
94
95
  other_role_method += "_as_#{other_role_name}"
95
96
  end
96
97
  end
97
98
 
98
99
  role_name = role_method
99
- role_name = nil if role_name == role.concept.name.snakecase
100
+ role_name = nil if role_name == role.concept.name.gsub(/ /,'_').snakecase
100
101
 
101
102
  binary_dump(role, other_role_name, other_player, role.is_mandatory, one_to_one, nil, role_name, other_role_method)
102
103
  end
@@ -105,7 +106,7 @@ module ActiveFacts
105
106
  return "" if role.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
106
107
 
107
108
  if is_for && role.fact_type.entity_type == is_for && role.fact_type.all_role.size == 1
108
- return role.concept.name.snakecase
109
+ return role.concept.name.gsub(/[- ]/,'_').snakecase
109
110
  end
110
111
 
111
112
  # debug "Looking for preferred_role_name of #{describe_fact_type(role.fact_type, role)}"
@@ -117,7 +118,7 @@ module ActiveFacts
117
118
  # Unaries are a hack, with only one role for what is effectively a binary:
118
119
  if (role.fact_type.all_role.size == 1)
119
120
  return (role.role_name && role.role_name.snakecase) ||
120
- reading.text.gsub(/ *\{0\} */,'').gsub(' ','_').downcase
121
+ reading.text.gsub(/ *\{0\} */,'').gsub(/[- ]/,'_').downcase
121
122
  end
122
123
 
123
124
  # debug "\tleading_adjective=#{(p=preferred_role_ref).leading_adjective}, role_name=#{role.role_name}, role player=#{role.concept.name}, trailing_adjective=#{p.trailing_adjective}"
@@ -129,13 +130,13 @@ module ActiveFacts
129
130
  la = preferred_role_ref.leading_adjective
130
131
  role_words << la.gsub(/ /,'_') if la && la != "" and !role.role_name
131
132
 
132
- role_words << (role_name || role.concept.name)
133
+ role_words << (role_name || role.concept.name.gsub(/ /,'_'))
133
134
  # REVISIT: Same when trailing_adjective is a suffix of the role_name
134
135
  ta = preferred_role_ref.trailing_adjective
135
136
  role_words << ta.gsub(/ /,'_') if ta && ta != "" and !role_name
136
137
  n = role_words.map{|w| w.gsub(/([a-z])([A-Z]+)/,'\1_\2').downcase}*"_"
137
138
  # debug "\tresult=#{n}"
138
- n
139
+ n.gsub(' ','_')
139
140
  end
140
141
 
141
142
  def skip_fact_type(f)
@@ -156,10 +157,10 @@ module ActiveFacts
156
157
  pc.max_frequency == 1
157
158
  }
158
159
  }
159
- as = role_name != role.concept.name.snakecase ? "_as_#{role_name}" : ""
160
+ as = role_name != role.concept.name.gsub(/ /,'_').snakecase ? "_as_#{role_name}" : ""
160
161
  raise "Fact #{fact_type.describe} type is not objectified" unless fact_type.entity_type
161
162
  other_role_method = (one_to_one ? "" : "all_") +
162
- fact_type.entity_type.name.snakecase +
163
+ fact_type.entity_type.name.gsub(/ /,'_').snakecase +
163
164
  as
164
165
  binary_dump(role, role_name, role.concept, true, one_to_one, nil, nil, other_role_method)
165
166
  }
@@ -34,6 +34,7 @@ module ActiveFacts
34
34
  build_indices
35
35
  @concept_types_dumped = {}
36
36
  @fact_types_dumped = {}
37
+ units_dump()
37
38
  value_types_dump()
38
39
  entity_types_dump()
39
40
  fact_types_dump()
@@ -62,10 +63,32 @@ module ActiveFacts
62
63
  @constraints_used = {}
63
64
  end
64
65
 
66
+ def units_dump
67
+ done_banner = false
68
+ units = @vocabulary.all_unit.to_a.sort_by{|u| u.name.gsub(/ /,'')}
69
+ while units.size > 0
70
+ if !done_banner
71
+ done_banner = true
72
+ units_banner
73
+ end
74
+ i = 0
75
+ while i < units.size
76
+ unit = units[i]
77
+ i += 1
78
+ # Skip this one if the precursors haven't yet been dumped:
79
+ next if unit.all_derivation_as_derived_unit.detect{|d| units.include?(d.base_unit) }
80
+
81
+ unit_dump(unit)
82
+ units.delete(unit)
83
+ i -= 1
84
+ end
85
+ end
86
+ end
87
+
65
88
  def value_types_dump
66
89
  done_banner = false
67
90
  @value_type_dumped = {}
68
- @vocabulary.all_concept.sort_by{|o| o.name}.each{|o|
91
+ @vocabulary.all_concept.sort_by{|o| o.name.gsub(/ /,'')}.each{|o|
69
92
  next unless o.is_a?(ActiveFacts::Metamodel::ValueType)
70
93
 
71
94
  value_type_banner unless done_banner
@@ -81,7 +104,7 @@ module ActiveFacts
81
104
  def value_type_chain_dump(o)
82
105
  return if @value_type_dumped[o]
83
106
  value_type_chain_dump(o.supertype) if (o.supertype && !@value_type_dumped[o.supertype])
84
- value_type_dump(o)
107
+ value_type_dump(o) if o.name != "_ImplicitBooleanValueType"
85
108
  @value_type_dumped[o] = true
86
109
  end
87
110
 
@@ -95,7 +118,7 @@ module ActiveFacts
95
118
  done_banner = false
96
119
  sorted = @vocabulary.all_concept.select{|o|
97
120
  o.is_a?(ActiveFacts::Metamodel::EntityType) # and !o.fact_type
98
- }.sort_by{|o| o.name}
121
+ }.sort_by{|o| o.name.gsub(/ /,'')}
99
122
  panic = nil
100
123
  while true do
101
124
  count_this_pass = 0
@@ -181,99 +204,17 @@ module ActiveFacts
181
204
  # Here, we must find the role_ref containing the adjectives that we need for each identifier,
182
205
  # which will be attached to the uniqueness constraint on this object in the binary FT that
183
206
  # attaches that identifying role.
184
- role_refs = pi.role_sequence.all_role_ref.sort_by{|role_ref| role_ref.ordinal}
207
+ identifying_role_refs = pi.role_sequence.all_role_ref.sort_by{|role_ref| role_ref.ordinal}
185
208
 
186
209
  # We need to get the adjectives for the roles from the identifying fact's preferred readings:
187
- identifying_facts = ([o.fact_type]+role_refs.map{|rr| rr.role.fact_type }).compact.uniq
188
- preferred_readings = identifying_facts.inject({}){|reading_hash, fact_type|
189
- pr = fact_type.preferred_reading
190
- reading_hash[fact_type] = pr
191
- reading_hash
192
- }
193
- #p identifying_facts.map{|f| f.preferred_reading }
210
+ identifying_facts = ([o.fact_type]+identifying_role_refs.map{|rr| rr.role.fact_type }).compact.uniq
194
211
 
195
- identifying_roles = role_refs.map(&:role)
196
- identification = identified_by_roles_and_facts(o, identifying_roles, identifying_facts, preferred_readings)
212
+ identification = identified_by_roles_and_facts(o, identifying_role_refs, identifying_facts)
197
213
  #identifying_facts.each{|f| @fact_types_dumped[f] = true }
198
214
 
199
215
  identification
200
216
  end
201
217
 
202
- def fact_readings_with_constraints(fact_type, fact_constraints = nil)
203
- define_role_names = true
204
- fact_constraints ||= @presence_constraints_by_fact[fact_type]
205
- readings = fact_type.all_reading_by_ordinal.inject([]) do |reading_array, reading|
206
- reading_array << expanded_reading(reading, fact_constraints, define_role_names)
207
-
208
- define_role_names = false # No need to define role names in subsequent readings
209
-
210
- reading_array
211
- end
212
-
213
- readings
214
- end
215
-
216
- def expanded_reading(reading, fact_constraints, define_role_names)
217
- # Find all role numbers in order of occurrence in this reading:
218
- role_refs = reading.role_sequence.all_role_ref.sort_by{|role_ref| role_ref.ordinal}
219
- role_numbers = reading.text.scan(/\{(\d)\}/).flatten.map{|m| Integer(m) }
220
- roles = role_numbers.map{|m| role_refs[m].role }
221
- # debug "Considering #{reading.text} having #{role_numbers.inspect}"
222
-
223
- # Find the constraints that constrain frequency over each role we can verbalise:
224
- frequency_constraints = []
225
- value_restrictions = []
226
- roles.each do |role|
227
- # Find a mandatory constraint that's *not* unique; this will need an extra reading
228
- role_is_first_in = reading.fact_type.all_reading.detect{|r|
229
- role == r.role_sequence.all_role_ref.sort_by{|role_ref|
230
- role_ref.ordinal
231
- }[0].role
232
- }
233
-
234
- if vr = role.role_value_restriction
235
- if @constraints_used[vr]
236
- vr = nil
237
- else
238
- @constraints_used[vr] = true
239
- vr = vr.describe
240
- end
241
- end
242
- value_restrictions << vr
243
- if (role == roles.last) # First role of the reading?
244
- # REVISIT: With a ternary, doing this on other than the last role can be ambiguous,
245
- # in case both the 2nd and 3rd roles have frequencies. Think some more!
246
-
247
- constraint = fact_constraints.find{|c| # Find a UC that spans all other Roles
248
- # internal uniqueness constraints span all roles but one, the residual:
249
- c.is_a?(ActiveFacts::Metamodel::PresenceConstraint) &&
250
- !@constraints_used[c] && # Already verbalised
251
- roles-c.role_sequence.all_role_ref.map(&:role) == [role]
252
- }
253
- # Index the frequency implied by the constraint under the role position in the reading
254
- if constraint # Mark this constraint as "verbalised" so we don't do it again:
255
- @constraints_used[constraint] = true
256
- end
257
- frequency_constraints << show_frequency(role, constraint)
258
- else
259
- frequency_constraints << show_frequency(role, nil)
260
- end
261
- end
262
-
263
- expanded = reading.expand(frequency_constraints, define_role_names, value_restrictions)
264
-
265
- if (ft_rings = @ring_constraints_by_fact[reading.fact_type]) &&
266
- (ring = ft_rings.detect{|rc| !@constraints_used[rc]})
267
- @constraints_used[ring] = true
268
- append_ring_to_reading(expanded, ring)
269
- end
270
- expanded
271
- end
272
-
273
- def show_frequency role, constraint
274
- constraint ? constraint.frequency : nil
275
- end
276
-
277
218
  def describe_fact_type(fact_type, highlight = nil)
278
219
  (fact_type.entity_type ? fact_type.entity_type.name : "")+
279
220
  describe_roles(fact_type.all_role, highlight)
@@ -347,6 +288,7 @@ module ActiveFacts
347
288
  roles.map(&:fact_type).uniq.select{|fact_type|
348
289
  # The fact type hasn't already been dumped but all its role players have
349
290
  !@fact_types_dumped[fact_type] &&
291
+ !fact_type.is_a?(ActiveFacts::Metamodel::ImplicitFactType) &&
350
292
  !fact_type.all_role.detect{|r| !@concept_types_dumped[r.concept] } &&
351
293
  !fact_type.entity_type
352
294
  # !(fact_type.entity_type && (p = @precursors[fact_type.entity_type]) && p.size > 0)
@@ -402,28 +344,6 @@ module ActiveFacts
402
344
  @concept_types_dumped[fact_type.entity_type] = true if fact_type.entity_type
403
345
  end
404
346
 
405
- # Arrange for objectified fact types to appear in order of name, after other fact types.
406
- # Facts are ordered alphabetically by the names of their role players,
407
- # then by preferred_reading (subtyping fact types have no preferred_reading).
408
- def fact_type_key(fact_type)
409
- role_names =
410
- if (pr = fact_type.preferred_reading)
411
- pr.role_sequence.
412
- all_role_ref.
413
- sort_by{|role_ref| role_ref.ordinal}.
414
- map{|role_ref| [ role_ref.leading_adjective, role_ref.role.concept.name, role_ref.trailing_adjective ].compact*"-" } +
415
- [pr.text]
416
- else
417
- fact_type.all_role.map{|role| role.concept.name }
418
- end
419
-
420
- (fact_type.entity_type ? [fact_type.entity_type.name] : [""]) + role_names
421
- end
422
-
423
- def role_ref_key(role_ref)
424
- [ role_ref.leading_adjective, role_ref.role.concept.name, role_ref.trailing_adjective ].compact*"-"
425
- end
426
-
427
347
  # Dump fact types.
428
348
  def fact_types_dump
429
349
  # REVISIT: Uniqueness on the LHS of a binary can be coded using "distinct"
@@ -437,6 +357,7 @@ module ActiveFacts
437
357
  fact_collection.keys.select{|fact_id|
438
358
  fact_type = fact_collection[fact_id] and
439
359
  !fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance) and
360
+ !fact_type.is_a?(ActiveFacts::Metamodel::ImplicitFactType) and
440
361
  !@fact_types_dumped[fact_type] and
441
362
  !skip_fact_type(fact_type) and
442
363
  !fact_type.all_role.detect{|r| r.concept.is_a?(ActiveFacts::Metamodel::EntityType) }
@@ -453,7 +374,8 @@ module ActiveFacts
453
374
 
454
375
  # REVISIT: Find out why some fact types are missed during entity dumping:
455
376
  @vocabulary.constellation.FactType.values.select{|fact_type|
456
- !fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
377
+ !fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance) &&
378
+ !fact_type.is_a?(ActiveFacts::Metamodel::ImplicitFactType)
457
379
  }.sort_by{|fact_type|
458
380
  fact_type_key(fact_type)
459
381
  }.each{|fact_type|
@@ -481,16 +403,73 @@ module ActiveFacts
481
403
  }
482
404
  end
483
405
 
406
+ # Arrange for objectified fact types to appear in order of name, after other fact types.
407
+ # Facts are ordered alphabetically by the names of their role players,
408
+ # then by preferred_reading (subtyping fact types have no preferred_reading).
409
+ def fact_type_key(fact_type)
410
+ role_names =
411
+ if (pr = fact_type.preferred_reading)
412
+ pr.role_sequence.
413
+ all_role_ref.
414
+ sort_by{|role_ref| role_ref.ordinal}.
415
+ map{|role_ref| [ role_ref.leading_adjective, role_ref.role.concept.name, role_ref.trailing_adjective ].compact*"-" } +
416
+ [pr.text]
417
+ else
418
+ fact_type.all_role.map{|role| role.concept.name }
419
+ end
420
+
421
+ (fact_type.entity_type ? [fact_type.entity_type.name] : [""]) + role_names
422
+ end
423
+
424
+ def role_ref_key(role_ref)
425
+ [ role_ref.leading_adjective, role_ref.role.concept.name, role_ref.trailing_adjective ].compact*"-" +
426
+ " in " +
427
+ role_ref.role.fact_type.preferred_reading.expand
428
+ end
429
+
484
430
  def constraint_sort_key(c)
485
431
  case c
486
432
  when ActiveFacts::Metamodel::RingConstraint
487
- [1, c.ring_type, c.role.concept.name, c.other_role.concept.name, c.name||""]
488
- when ActiveFacts::Metamodel::SetComparisonConstraint
489
- [2, c.all_set_comparison_roles.map{|scrs| scrs.role_sequence.all_role_ref.map{|rr| role_ref_key(rr)}}, c.name||""]
433
+ [ 1,
434
+ c.ring_type,
435
+ c.role.concept.name,
436
+ c.other_role.concept.name,
437
+ c.name||""
438
+ ]
439
+ when ActiveFacts::Metamodel::SetExclusionConstraint
440
+ [ 2+(c.is_mandatory ? 0 : 1),
441
+ c.all_set_comparison_roles.map{|scrs|
442
+ scrs.role_sequence.all_role_ref.map{|rr|
443
+ role_ref_key(rr)
444
+ }
445
+ },
446
+ c.name||""
447
+ ]
448
+ when ActiveFacts::Metamodel::SetEqualityConstraint
449
+ [ 4,
450
+ c.all_set_comparison_roles.map{|scrs|
451
+ scrs.role_sequence.all_role_ref.map{|rr|
452
+ role_ref_key(rr)
453
+ }
454
+ },
455
+ c.name||""
456
+ ]
490
457
  when ActiveFacts::Metamodel::SubsetConstraint
491
- [3, [c.superset_role_sequence, c.subset_role_sequence].map{|rs| rs.all_role_ref.map{|rr| role_ref_key(rr)}}, c.name||""]
458
+ [ 5,
459
+ [c.superset_role_sequence, c.subset_role_sequence].map{|rs|
460
+ rs.all_role_ref.map{|rr|
461
+ role_ref_key(rr)
462
+ }
463
+ },
464
+ c.name||""
465
+ ]
492
466
  when ActiveFacts::Metamodel::PresenceConstraint
493
- [4, c.role_sequence.all_role_ref.map{|rr| role_ref_key(rr)}, c.name||""]
467
+ [ 6,
468
+ c.role_sequence.all_role_ref.map{|rr|
469
+ role_ref_key(rr)
470
+ },
471
+ c.name||""
472
+ ]
494
473
  end
495
474
  end
496
475
 
@@ -501,9 +480,14 @@ module ActiveFacts
501
480
  if c.is_a?(ActiveFacts::Metamodel::PresenceConstraint)
502
481
  # Skip uniqueness constraints that cover all roles of a fact type, they're implicit
503
482
  fact_types = c.role_sequence.all_role_ref.map{|rr| rr.role.fact_type}.uniq
504
- next if fact_types.size == 1 &&
483
+ if fact_types.size == 1 &&
484
+ !c.role_sequence.all_role_ref.detect{|rr| rr.join_node } &&
505
485
  c.max_frequency == 1 && # Uniqueness
506
486
  fact_types[0].all_role.size == c.role_sequence.all_role_ref.size
487
+ # debugger if !$constraint_id || c.constraint_id.object_id == $foo
488
+ # $constraint_id ||= 1
489
+ next
490
+ end
507
491
 
508
492
  # Skip internal PresenceConstraints over TypeInheritances:
509
493
  next if c.role_sequence.all_role_ref.size == 1 &&
@@ -529,6 +513,12 @@ module ActiveFacts
529
513
  debug "Should override vocabulary_end"
530
514
  end
531
515
 
516
+ def units_banner
517
+ end
518
+
519
+ def unit_dump unit
520
+ end
521
+
532
522
  def value_type_banner
533
523
  debug "Should override value_type_banner"
534
524
  end
@@ -45,38 +45,34 @@ module ActiveFacts
45
45
  end
46
46
 
47
47
  def value_type_dump(o)
48
- is_special_supertype = !o.supertype && %w{Date Time DateAndTime}.include?(o.name)
49
-
50
- # We map DateAndTime to DateTime; if such a ValueType exists, don't dump this one
51
- return if is_special_supertype && o.name == 'DateAndTime' && o.constellation.ValueType[[[o.vocabulary.name], 'DateTime']]
52
-
53
- return if !o.supertype && !is_special_supertype
54
- if o.supertype && o.name == o.supertype.name
55
- # In ActiveFacts, parameterising a ValueType will create a new ValueType
56
- # throw Can't handle parameterized value type of same name as its ValueType" if ...
57
- end
58
-
59
48
  length = (l = o.length) && l > 0 ? ":length => #{l}" : nil
60
49
  scale = (s = o.scale) && s > 0 ? ":scale => #{s}" : nil
61
50
  params = [length,scale].compact * ", "
62
51
 
52
+ return if
53
+ !o.supertype && # No supertype, i.e. a base type
54
+ o.all_role.size == 0 && # No roles
55
+ !o.is_independent && # not independent
56
+ o.all_instance.size == 0 # No instances
57
+
63
58
  name = o.name
64
59
  ruby_type_name =
65
- case o.supertype ? o.supertype.name : o.name
66
- when "VariableLengthText"; "String"
67
- when "Date"; "::Date"
68
- when "DateAndTime"; "::DateTime"
69
- when "Time"; "::Time"
70
- else o.supertype.name
71
- end
72
-
73
- name = name.sub(/^[a-z]/) {|i| i.upcase}
60
+ if o.supertype
61
+ o.supertype.name.gsub(/ /,'')
62
+ else
63
+ o.name.gsub(/ /,'')
64
+ end
65
+ name = name.sub(/^[a-z]/) {|i| i.upcase}.gsub(/ /,'')
66
+ if ruby_type_name == name
67
+ ruby_type_name = '::'+ruby_type_name
68
+ end
69
+
74
70
  puts " class #{name} < #{ruby_type_name}\n" +
75
71
  " value_type #{params}\n"
76
72
  if @sql and o.is_table
77
73
  puts " table"
78
74
  end
79
- puts " restrict #{o.value_restriction.all_allowed_range_sorted.map{|ar| ar.to_s}*", "}\n" if o.value_restriction
75
+ puts " restrict #{o.value_constraint.all_allowed_range_sorted.map{|ar| ar.to_s}*", "}\n" if o.value_constraint
80
76
  puts " \# REVISIT: #{o.name} is in units of #{o.unit.name}\n" if o.unit
81
77
  roles_dump(o)
82
78
  puts " end\n\n"
@@ -86,9 +82,9 @@ module ActiveFacts
86
82
  primary_supertype = o && (o.identifying_supertype || o.supertypes[0])
87
83
  secondary_supertypes = o.supertypes-[primary_supertype]
88
84
 
89
- puts " class #{o.name} < #{ primary_supertype.name }"
85
+ puts " class #{o.name.gsub(/ /,'')} < #{ primary_supertype.name.gsub(/ /,'') }"
90
86
  puts " identified_by #{identified_by(o, pi)}" if pi
91
- puts " supertypes "+secondary_supertypes.map(&:name)*", " if secondary_supertypes.size > 0
87
+ puts " supertypes "+secondary_supertypes.map{|st| st.name.gsub(/ /,'')}*", " if secondary_supertypes.size > 0
92
88
  if @sql and o.is_table
93
89
  puts " table"
94
90
  end
@@ -99,7 +95,7 @@ module ActiveFacts
99
95
  end
100
96
 
101
97
  def non_subtype_dump(o, pi)
102
- puts " class #{o.name}"
98
+ puts " class #{o.name.gsub(/ /,'')}"
103
99
 
104
100
  # We want to name the absorption role only when it's absorbed along its single identifying role.
105
101
  puts " identified_by #{identified_by(o, pi)}"
@@ -124,10 +120,10 @@ module ActiveFacts
124
120
  pi = o.preferred_identifier
125
121
  pi = nil if pi && primary_supertype && primary_supertype.preferred_identifier == pi
126
122
 
127
- puts " class #{name}" +
128
- (primary_supertype ? " < "+primary_supertype.name : "") +
123
+ puts " class #{name.gsub(/ /,'')}" +
124
+ (primary_supertype ? " < "+primary_supertype.name.gsub(/ /,'') : "") +
129
125
  "\n" +
130
- secondary_supertypes.map{|sst| " supertype :#{sst.name}"}*"\n" +
126
+ secondary_supertypes.map{|sst| " supertype :#{sst.name.gsub(/ /,'_')}"}*"\n" +
131
127
  (pi ? " identified_by #{identified_by(o, pi)}" : "")
132
128
  puts " table" if @sql and o.is_table
133
129
  fact_roles_dump(fact_type)
@@ -137,9 +133,9 @@ module ActiveFacts
137
133
  @fact_types_dumped[fact_type] = true
138
134
  end
139
135
 
140
- def identified_by_roles_and_facts(entity_type, identifying_roles, identifying_facts, preferred_readings)
141
- identifying_roles.map{|role|
142
- ":"+preferred_role_name(role, entity_type)
136
+ def identified_by_roles_and_facts(entity_type, identifying_role_refs, identifying_facts)
137
+ identifying_role_refs.map{|role_ref|
138
+ ":"+preferred_role_name(role_ref.role, entity_type)
143
139
  }*", "
144
140
  end
145
141
 
@@ -149,33 +145,33 @@ module ActiveFacts
149
145
 
150
146
  def binary_dump(role, role_name, role_player, mandatory = nil, one_to_one = nil, readings = nil, other_role_name = nil, other_method_name = nil)
151
147
  # Find whether we need the name of the other role player, and whether it's defined yet:
152
- if role_name.camelcase(true) == role_player.name.sub(/^[a-z]/) {|i| i.upcase}
148
+ if role_name.camelcase(true) == role_player.name.gsub(/ /,'').sub(/^[a-z]/) {|i| i.upcase}
153
149
  # Don't use Class name if implied by rolename
154
150
  role_reference = nil
155
151
  else
156
152
  role_reference = ":class => "+concept_reference(role_player)
157
153
  end
158
- other_role_name = ":counterpart => :"+other_role_name if other_role_name
154
+ other_role_name = ":counterpart => :"+other_role_name.gsub(/ /,'_') if other_role_name
159
155
 
160
156
  line = " #{one_to_one ? "one_to_one" : "has_one" } " +
161
- [ ":"+role_name,
157
+ [ ":"+role_name.gsub(/ /,'_'),
162
158
  role_reference,
163
159
  mandatory ? ":mandatory => true" : nil,
164
160
  readings,
165
161
  other_role_name,
166
- (vr = role.role_value_restriction) ? ":restrict => #{vr}" : nil
162
+ (vr = role.role_value_constraint) ? ":restrict => #{vr}" : nil
167
163
  ].compact*", "+" "
168
164
  line += " "*(48-line.length) if line.length < 48
169
- line += "\# See #{role_player.name}.#{other_method_name}" if other_method_name
165
+ line += "\# See #{role_player.name.gsub(/ /,'')}.#{other_method_name}" if other_method_name
170
166
  puts line
171
- #puts " \# REVISIT: #{other_role_name} has values restricted to #{role.role_value_restriction}\n" if role.role_value_restriction
167
+ #puts " \# REVISIT: #{other_role_name} has values restricted to #{role.role_value_constraint}\n" if role.role_value_constraint
172
168
  end
173
169
 
174
170
  def concept_reference concept
175
171
  if !@concept_types_dumped[concept]
176
- '"'+concept.name+'"'
172
+ '"'+concept.name.gsub(/ /,'')+'"'
177
173
  else
178
- role_reference = concept.name
174
+ role_reference = concept.name.gsub(/ /,'')
179
175
  end
180
176
  end
181
177