activefacts 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest.txt +4 -0
- data/examples/CQL/Metamodel.cql +11 -7
- data/lib/activefacts/api/concept.rb +10 -0
- data/lib/activefacts/api/entity.rb +2 -0
- data/lib/activefacts/api/instance_index.rb +71 -0
- data/lib/activefacts/api/role_proxy.rb +70 -0
- data/lib/activefacts/api/role_values.rb +117 -0
- data/lib/activefacts/generate/absorption.rb +20 -30
- data/lib/activefacts/generate/null.rb +1 -0
- data/lib/activefacts/generate/ruby.rb +12 -28
- data/lib/activefacts/generate/sql/server.rb +8 -22
- data/lib/activefacts/generate/text.rb +1 -0
- data/lib/activefacts/input/cql.rb +30 -32
- data/lib/activefacts/input/orm.rb +11 -12
- data/lib/activefacts/persistence.rb +5 -0
- data/lib/activefacts/persistence/columns.rb +28 -21
- data/lib/activefacts/persistence/concept.rb +73 -0
- data/lib/activefacts/persistence/foreignkey.rb +17 -1
- data/lib/activefacts/persistence/index.rb +21 -10
- data/lib/activefacts/persistence/reference.rb +6 -6
- data/lib/activefacts/persistence/tables.rb +8 -5
- data/lib/activefacts/version.rb +1 -1
- data/lib/activefacts/vocabulary/extensions.rb +17 -7
- data/lib/activefacts/vocabulary/metamodel.rb +22 -17
- data/spec/absorption_spec.rb +1 -1
- data/spec/cql_symbol_tables_spec.rb +1 -1
- data/spec/cqldump_spec.rb +8 -8
- data/spec/norma_tables_spec.rb +1 -1
- metadata +7 -3
@@ -31,12 +31,13 @@ module ActiveFacts
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def vocabulary_start(vocabulary)
|
34
|
+
puts "require 'activefacts/api'\n"
|
34
35
|
if @sql
|
35
36
|
require 'activefacts/persistence'
|
37
|
+
puts "require 'activefacts/persistence'\n"
|
36
38
|
@tables = vocabulary.tables
|
37
39
|
end
|
38
|
-
puts "
|
39
|
-
puts "module #{vocabulary.name}\n\n"
|
40
|
+
puts "\nmodule #{vocabulary.name}\n\n"
|
40
41
|
end
|
41
42
|
|
42
43
|
def vocabulary_end
|
@@ -63,7 +64,7 @@ module ActiveFacts
|
|
63
64
|
|
64
65
|
puts " class #{o.name} < #{ruby_type_name}\n" +
|
65
66
|
" value_type #{params}\n"
|
66
|
-
puts " table" if @sql and
|
67
|
+
puts " table" if @sql and o.is_table
|
67
68
|
puts " \# REVISIT: #{o.name} has restricted values\n" if o.value_restriction
|
68
69
|
puts " \# REVISIT: #{o.name} is in units of #{o.unit.name}\n" if o.unit
|
69
70
|
roles_dump(o)
|
@@ -71,9 +72,13 @@ module ActiveFacts
|
|
71
72
|
end
|
72
73
|
|
73
74
|
def subtype_dump(o, supertypes, pi = nil)
|
74
|
-
|
75
|
+
primary_supertype = o && (o.identifying_supertype || o.supertypes[0])
|
76
|
+
secondary_supertypes = o.supertypes-[primary_supertype]
|
77
|
+
|
78
|
+
puts " class #{o.name} < #{ primary_supertype.name }"
|
75
79
|
puts " identified_by #{identified_by(o, pi)}" if pi
|
76
|
-
puts "
|
80
|
+
puts " supertypes "+secondary_supertypes.map(&:name)*", " if secondary_supertypes.size > 0
|
81
|
+
puts " table" if @sql and o.is_table
|
77
82
|
fact_roles_dump(o.fact_type) if o.fact_type
|
78
83
|
roles_dump(o)
|
79
84
|
puts " end\n\n"
|
@@ -83,7 +88,7 @@ module ActiveFacts
|
|
83
88
|
def non_subtype_dump(o, pi)
|
84
89
|
puts " class #{o.name}"
|
85
90
|
puts " identified_by #{identified_by(o, pi)}"
|
86
|
-
puts " table" if @sql and
|
91
|
+
puts " table" if @sql and o.is_table
|
87
92
|
fact_roles_dump(o.fact_type) if o.fact_type
|
88
93
|
roles_dump(o)
|
89
94
|
puts " end\n\n"
|
@@ -107,6 +112,7 @@ module ActiveFacts
|
|
107
112
|
"\n" +
|
108
113
|
secondary_supertypes.map{|sst| " supertype :#{sst.name}"}*"\n" +
|
109
114
|
(pi ? " identified_by #{identified_by(o, pi)}" : "")
|
115
|
+
puts " table" if @sql and o.is_table
|
110
116
|
fact_roles_dump(fact_type)
|
111
117
|
roles_dump(o)
|
112
118
|
puts " end\n\n"
|
@@ -120,32 +126,10 @@ module ActiveFacts
|
|
120
126
|
}*", "
|
121
127
|
end
|
122
128
|
|
123
|
-
def roles_dump(o)
|
124
|
-
@ar_by_role = nil
|
125
|
-
if @sql and @tables.include?(o)
|
126
|
-
ar = o.absorbed_roles
|
127
|
-
@ar_by_role = ar.all_role_ref.inject({}){|h,rr|
|
128
|
-
input_role = (j=rr.all_join_path).size > 0 ? j[0].input_role : rr.role
|
129
|
-
(h[input_role] ||= []) << rr
|
130
|
-
h
|
131
|
-
}
|
132
|
-
#puts ar.all_role_ref.map{|rr| "\t"+rr.describe}*"\n"
|
133
|
-
end
|
134
|
-
super
|
135
|
-
end
|
136
|
-
|
137
129
|
def unary_dump(role, role_name)
|
138
130
|
puts " maybe :"+role_name
|
139
131
|
end
|
140
132
|
|
141
|
-
def role_dump(role)
|
142
|
-
other_role = role.fact_type.all_role.select{|r| r != role}[0] || role
|
143
|
-
if @ar_by_role and @ar_by_role[other_role] and @sql
|
144
|
-
puts " # role #{role.fact_type.describe(role)}: absorbs in through #{preferred_role_name(other_role)}: "+@ar_by_role[other_role].map(&:column_name)*", "
|
145
|
-
end
|
146
|
-
super
|
147
|
-
end
|
148
|
-
|
149
133
|
def binary_dump(role, role_name, role_player, one_to_one = nil, readings = nil, other_role_name = nil, other_method_name = nil)
|
150
134
|
# Find whether we need the name of the other role player, and whether it's defined yet:
|
151
135
|
if role_name.camelcase(true) == role_player.name
|
@@ -116,7 +116,7 @@ module ActiveFacts
|
|
116
116
|
tables_emitted = {}
|
117
117
|
delayed_foreign_keys = []
|
118
118
|
|
119
|
-
@vocabulary.tables.
|
119
|
+
@vocabulary.tables.each do |table|
|
120
120
|
puts "CREATE TABLE #{escape table.name} ("
|
121
121
|
|
122
122
|
pk = table.identifier_columns
|
@@ -127,9 +127,9 @@ module ActiveFacts
|
|
127
127
|
column.references[0].is_simple_reference
|
128
128
|
end
|
129
129
|
|
130
|
-
|
131
|
-
|
132
|
-
|
130
|
+
# We sort the columns here, not in the persistence layer, because it affects
|
131
|
+
# the ordering of columns in an index :-(.
|
132
|
+
columns = table.columns.sort_by { |column| column.name(nil) }.map do |column|
|
133
133
|
name = escape column.name("")
|
134
134
|
padding = " "*(name.size >= ColumnNameMax ? 1 : ColumnNameMax-name.size)
|
135
135
|
type, params, restrictions = column.type
|
@@ -158,22 +158,11 @@ module ActiveFacts
|
|
158
158
|
")"
|
159
159
|
|
160
160
|
inline_fks = []
|
161
|
-
table.foreign_keys.
|
162
|
-
# Put the Foreign keys in a defined order:
|
163
|
-
[ fk.to.name,
|
164
|
-
fk.to_columns.map{|col| col.name(nil).sort},
|
165
|
-
fk.from_columns.map{|col| col.name(nil).sort}
|
166
|
-
]
|
167
|
-
end.each do |fk|
|
168
|
-
# Put the column pairs in a defined order, sorting key pairs by to-name:
|
169
|
-
froms, tos = fk.from_columns.zip(fk.to_columns).sort_by { |pair|
|
170
|
-
pair[1].name(nil)
|
171
|
-
}.transpose
|
172
|
-
|
161
|
+
table.foreign_keys.each do |fk|
|
173
162
|
fk_text = "FOREIGN KEY (" +
|
174
|
-
|
163
|
+
fk.from_columns.map{|column| column.name}*", " +
|
175
164
|
") REFERENCES #{escape fk.to.name} (" +
|
176
|
-
|
165
|
+
fk.to_columns.map{|column| column.name}*", " +
|
177
166
|
")"
|
178
167
|
if !@delay_fks and # We don't want to delay all Fks
|
179
168
|
(tables_emitted[fk.to] or # The target table has been emitted
|
@@ -187,10 +176,7 @@ module ActiveFacts
|
|
187
176
|
indices = table.indices
|
188
177
|
inline_indices = []
|
189
178
|
delayed_indices = []
|
190
|
-
indices.
|
191
|
-
# Put the indices in a defined order:
|
192
|
-
index.columns.map(&:name)
|
193
|
-
end.each do |index|
|
179
|
+
indices.each do |index|
|
194
180
|
next if index.over == table && index.is_primary # Already did the primary keys
|
195
181
|
abbreviated_column_names = index.abbreviated_column_names*""
|
196
182
|
column_names = index.column_names
|
@@ -1,5 +1,3 @@
|
|
1
|
-
#
|
2
|
-
# ActiveFacts Vocabulary Input.
|
3
1
|
# Compile a CQL file into an ActiveFacts vocabulary.
|
4
2
|
#
|
5
3
|
# Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
|
@@ -97,15 +95,15 @@ module ActiveFacts
|
|
97
95
|
# Create the base type:
|
98
96
|
base_type = nil
|
99
97
|
if (base_type_name != name)
|
100
|
-
unless base_type = @constellation.ValueType[[@constellation.Name(base_type_name)
|
98
|
+
unless base_type = @constellation.ValueType[[@vocabulary, @constellation.Name(base_type_name)]]
|
101
99
|
#puts "REVISIT: Creating base ValueType #{base_type_name} in #{@vocabulary.inspect}"
|
102
|
-
base_type = @constellation.ValueType(
|
100
|
+
base_type = @constellation.ValueType(@vocabulary, base_type_name)
|
103
101
|
return if base_type_name == name
|
104
102
|
end
|
105
103
|
end
|
106
104
|
|
107
105
|
# Create and initialise the ValueType:
|
108
|
-
vt = @constellation.ValueType(
|
106
|
+
vt = @constellation.ValueType(@vocabulary, name)
|
109
107
|
vt.supertype = base_type if base_type
|
110
108
|
vt.length = length if length
|
111
109
|
vt.scale = scale if scale
|
@@ -120,7 +118,7 @@ module ActiveFacts
|
|
120
118
|
min ? [min.to_s, true] : nil,
|
121
119
|
max ? [max.to_s, true] : nil
|
122
120
|
)
|
123
|
-
ar = @constellation.AllowedRange(
|
121
|
+
ar = @constellation.AllowedRange(vt.value_restriction, v_range)
|
124
122
|
end
|
125
123
|
end
|
126
124
|
end
|
@@ -130,7 +128,7 @@ module ActiveFacts
|
|
130
128
|
debug :entity, "Defining Entity Type #{name}" do
|
131
129
|
# Assert the entity:
|
132
130
|
# If this entity was forward referenced, this won't be a new object, and will subsume its roles
|
133
|
-
entity_type = @constellation.EntityType(
|
131
|
+
entity_type = @constellation.EntityType(@vocabulary, name)
|
134
132
|
|
135
133
|
# Set up its supertypes:
|
136
134
|
supertypes.each do |supertype_name|
|
@@ -162,9 +160,9 @@ module ActiveFacts
|
|
162
160
|
|
163
161
|
# Find or Create an appropriate ValueType called "#{name}#{mode}", of the supertype "#{mode}"
|
164
162
|
vt_name = "#{name}#{mode}"
|
165
|
-
unless vt = @constellation.ValueType[[
|
166
|
-
base_vt = @constellation.ValueType(
|
167
|
-
vt = @constellation.ValueType(
|
163
|
+
unless vt = @constellation.ValueType[[@vocabulary, vt_name]]
|
164
|
+
base_vt = @constellation.ValueType(@vocabulary, mode)
|
165
|
+
vt = @constellation.ValueType(@vocabulary, vt_name, :supertype => base_vt)
|
168
166
|
end
|
169
167
|
end
|
170
168
|
|
@@ -373,7 +371,7 @@ module ActiveFacts
|
|
373
371
|
|
374
372
|
def add_supertype(entity_type, supertype_name, identifying_supertype)
|
375
373
|
debug :supertype, "Supertype #{supertype_name}"
|
376
|
-
supertype = @constellation.EntityType(
|
374
|
+
supertype = @constellation.EntityType(@vocabulary, supertype_name)
|
377
375
|
inheritance_fact = @constellation.TypeInheritance(entity_type, supertype, :fact_type_id => :new)
|
378
376
|
|
379
377
|
# Create a reading:
|
@@ -459,7 +457,7 @@ module ActiveFacts
|
|
459
457
|
|
460
458
|
# The fact type has a name iff it's objectified as an entity type
|
461
459
|
#puts "============= Creating entity #{name} to nominalize fact type #{fact_type.default_reading} ======================" if name
|
462
|
-
fact_type.entity_type = @constellation.EntityType(
|
460
|
+
fact_type.entity_type = @constellation.EntityType(@vocabulary, name) if name
|
463
461
|
|
464
462
|
# Add the identifying PresenceConstraint for this fact type:
|
465
463
|
if fact_type.all_role.size == 1 && !fact_type.entity_type
|
@@ -496,7 +494,7 @@ module ActiveFacts
|
|
496
494
|
# sequences. Each binding that isn't common at this top level
|
497
495
|
# must occur more than once in each group of fact types where
|
498
496
|
# it appears, and it forms a join between those fact types.
|
499
|
-
def
|
497
|
+
def bind_joins_as_role_sequences(readings_list)
|
500
498
|
@symbols = SymbolTable.new(@constellation, @vocabulary)
|
501
499
|
fact_roles_list = []
|
502
500
|
bindings_list = []
|
@@ -520,8 +518,8 @@ module ActiveFacts
|
|
520
518
|
end
|
521
519
|
|
522
520
|
# Each set of binding arrays in the list must share at least one common binding
|
523
|
-
|
524
|
-
common_bindings =
|
521
|
+
bindings_by_join = bindings_list.map{|join| join.flatten}
|
522
|
+
common_bindings = bindings_by_join[1..-1].inject(bindings_by_join[0]) { |c, b| c & b }
|
525
523
|
# Was:
|
526
524
|
# common_bindings = bindings_list.inject(bindings_list[0]) { |common, bindings| common & bindings }
|
527
525
|
raise "Set constraints must have at least one common role between the sets" unless common_bindings.size > 0
|
@@ -533,9 +531,9 @@ module ActiveFacts
|
|
533
531
|
# Each element of a join path is the array of bindings for a fact type invocation.
|
534
532
|
# Each invocation must share a binding (not one of the globally common ones) with
|
535
533
|
# another invocation in that join path.
|
536
|
-
bindings_list.each_with_index do |
|
534
|
+
bindings_list.each_with_index do |join, jpnum|
|
537
535
|
# Check that this bindings array creates a complete join path:
|
538
|
-
|
536
|
+
join.each_with_index do |bindings, i|
|
539
537
|
fact_type_roles = fact_roles_list[jpnum][i]
|
540
538
|
fact_type = fact_type_roles[0].fact_type
|
541
539
|
|
@@ -543,10 +541,10 @@ module ActiveFacts
|
|
543
541
|
# These bindings must be joined to some later fact type by a common binding that isn't a globally-common one:
|
544
542
|
local_bindings = bindings-common_bindings
|
545
543
|
next if local_bindings.size == 0 # No join path is required, as only one fact type is invoked.
|
546
|
-
next if i ==
|
544
|
+
next if i == join.size-1 # We already checked that the last fact type invocation is joined
|
547
545
|
ok = local_bindings.detect do |local_binding|
|
548
546
|
j = i+1
|
549
|
-
|
547
|
+
join[j..-1].detect do |other_bindings|
|
550
548
|
other_fact_type_roles = fact_roles_list[jpnum][j]
|
551
549
|
other_fact_type = other_fact_type_roles[0].fact_type
|
552
550
|
j += 1
|
@@ -568,10 +566,10 @@ module ActiveFacts
|
|
568
566
|
role_sequences = readings_list.map{|r| @constellation.RoleSequence(:new) }
|
569
567
|
common_bindings.each_with_index do |binding, index|
|
570
568
|
role_sequences.each_with_index do |rs, rsi|
|
571
|
-
|
569
|
+
join = bindings_list[rsi]
|
572
570
|
fact_pos = nil
|
573
|
-
join_pos = (0...
|
574
|
-
fact_pos =
|
571
|
+
join_pos = (0...join.size).detect do |i|
|
572
|
+
fact_pos = join[i].index(binding)
|
575
573
|
end
|
576
574
|
@constellation.RoleRef(rs, index).role = fact_roles_list[rsi][join_pos][fact_pos]
|
577
575
|
end
|
@@ -581,7 +579,7 @@ module ActiveFacts
|
|
581
579
|
end
|
582
580
|
|
583
581
|
def subset_constraint(subset_readings, superset_readings)
|
584
|
-
role_sequences =
|
582
|
+
role_sequences = bind_joins_as_role_sequences([subset_readings, superset_readings])
|
585
583
|
|
586
584
|
#puts "subset_constraint:\n\t#{subset_readings.inspect}\n\t#{superset_readings.inspect}"
|
587
585
|
#puts "\t#{role_sequences.map{|rs| rs.describe}.inspect}"
|
@@ -601,7 +599,7 @@ module ActiveFacts
|
|
601
599
|
# Exactly one or at most one, nothing else will do
|
602
600
|
raise "Set comparison constraint must use 'at most' or 'exactly' one" if quantifier[1] != 1
|
603
601
|
|
604
|
-
role_sequences =
|
602
|
+
role_sequences = bind_joins_as_role_sequences(readings_list)
|
605
603
|
|
606
604
|
# Create the constraint:
|
607
605
|
constraint = @constellation.SetExclusionConstraint(:new)
|
@@ -615,7 +613,7 @@ module ActiveFacts
|
|
615
613
|
def equality_constraint(*readings_list)
|
616
614
|
#puts "REVISIT: equality\n\t#{readings_list.map{|rl| rl.inspect}*"\n\tif and only if\n\t"}"
|
617
615
|
|
618
|
-
role_sequences =
|
616
|
+
role_sequences = bind_joins_as_role_sequences(readings_list)
|
619
617
|
|
620
618
|
# Create the constraint:
|
621
619
|
constraint = @constellation.SetEqualityConstraint(:new)
|
@@ -994,7 +992,7 @@ module ActiveFacts
|
|
994
992
|
return nil if roles.size == 0 # Safeguard; this would chuck an exception otherwise
|
995
993
|
roles[0].all_role_ref.each do |role_ref|
|
996
994
|
next if role_ref.role_sequence.all_role_ref.map(&:role) != roles
|
997
|
-
pc = role_ref.role_sequence.all_presence_constraint.
|
995
|
+
pc = role_ref.role_sequence.all_presence_constraint.single # Will return nil if there's more than one.
|
998
996
|
#puts "Existing PresenceConstraint matches those roles!" if pc
|
999
997
|
return pc if pc
|
1000
998
|
end
|
@@ -1018,15 +1016,15 @@ module ActiveFacts
|
|
1018
1016
|
end
|
1019
1017
|
|
1020
1018
|
def concept_by_name(name)
|
1021
|
-
player = @constellation.Concept[[
|
1019
|
+
player = @constellation.Concept[[@vocabulary.identifying_role_values, name]]
|
1022
1020
|
|
1023
1021
|
# REVISIT: Hack to allow facts to refer to standard types that will be imported from standard vocabulary:
|
1024
1022
|
if !player && %w{Date DateAndTime Time}.include?(name)
|
1025
|
-
player = @constellation.ValueType(
|
1023
|
+
player = @constellation.ValueType(@vocabulary.identifying_role_values, name)
|
1026
1024
|
end
|
1027
1025
|
|
1028
1026
|
if (!player && @symbols.allowed_forward[name])
|
1029
|
-
player = @constellation.EntityType(
|
1027
|
+
player = @constellation.EntityType(@vocabulary, name)
|
1030
1028
|
end
|
1031
1029
|
player
|
1032
1030
|
end
|
@@ -1173,15 +1171,15 @@ module ActiveFacts
|
|
1173
1171
|
# return the EntityType or ValueType this name refers to:
|
1174
1172
|
def concept(name, allowed_forward = false)
|
1175
1173
|
# See if the name is a defined concept in this vocabulary:
|
1176
|
-
player = @constellation.Concept[[
|
1174
|
+
player = @constellation.Concept[[virv = @vocabulary.identifying_role_values, name]]
|
1177
1175
|
|
1178
1176
|
# REVISIT: Hack to allow facts to refer to standard types that will be imported from standard vocabulary:
|
1179
1177
|
if !player && %w{Date DateAndTime Time}.include?(name)
|
1180
|
-
player = @constellation.ValueType(
|
1178
|
+
player = @constellation.ValueType(virv, name)
|
1181
1179
|
end
|
1182
1180
|
|
1183
1181
|
if !player && allowed_forward
|
1184
|
-
player = @constellation.EntityType(
|
1182
|
+
player = @constellation.EntityType(@vocabulary, name)
|
1185
1183
|
end
|
1186
1184
|
|
1187
1185
|
player
|
@@ -101,11 +101,11 @@ module ActiveFacts
|
|
101
101
|
entity_types <<
|
102
102
|
@by_id[id] =
|
103
103
|
entity_type =
|
104
|
-
@constellation.EntityType(
|
104
|
+
@constellation.EntityType(@vocabulary, name)
|
105
105
|
independent = x.attributes['IsIndependent']
|
106
106
|
entity_type.is_independent = true if independent && independent == 'true'
|
107
107
|
personal = x.attributes['IsPersonal']
|
108
|
-
entity_type.
|
108
|
+
entity_type.pronoun = 'personal' if personal && personal == 'true'
|
109
109
|
# x_pref = x.elements.to_a("orm:PreferredIdentifier")[0]
|
110
110
|
# if x_pref
|
111
111
|
# pi_id = x_pref.attributes['ref']
|
@@ -139,26 +139,26 @@ module ActiveFacts
|
|
139
139
|
length = 32 if type_name =~ /Integer\Z/ && length.to_i == 0 # Set default integer length
|
140
140
|
|
141
141
|
# REVISIT: Need to handle standard types better here:
|
142
|
-
data_type = type_name != name ? @constellation.ValueType(
|
142
|
+
data_type = type_name != name ? @constellation.ValueType(@vocabulary, type_name) : nil
|
143
143
|
|
144
144
|
# puts "ValueType #{name} is #{id}"
|
145
145
|
value_types <<
|
146
146
|
@by_id[id] =
|
147
|
-
vt = @constellation.ValueType(
|
147
|
+
vt = @constellation.ValueType(@vocabulary, name)
|
148
148
|
vt.supertype = data_type
|
149
149
|
vt.length = length if length
|
150
150
|
vt.scale = scale if scale
|
151
151
|
independent = x.attributes['IsIndependent']
|
152
152
|
vt.is_independent = true if independent && independent == 'true'
|
153
153
|
personal = x.attributes['IsPersonal']
|
154
|
-
vt.
|
154
|
+
vt.pronoun = 'personal' if personal && personal == 'true'
|
155
155
|
|
156
156
|
x_ranges = x.elements.to_a("orm:ValueRestriction/orm:ValueConstraint/orm:ValueRanges/orm:ValueRange")
|
157
157
|
next if x_ranges.size == 0
|
158
158
|
vt.value_restriction = @constellation.ValueRestriction(:new)
|
159
159
|
x_ranges.each{|x_range|
|
160
160
|
v_range = value_range(x_range)
|
161
|
-
ar = @constellation.AllowedRange(
|
161
|
+
ar = @constellation.AllowedRange(vt.value_restriction, v_range)
|
162
162
|
}
|
163
163
|
}
|
164
164
|
end
|
@@ -317,7 +317,7 @@ module ActiveFacts
|
|
317
317
|
#puts "NestedType #{name} is #{id}, nests #{fact_type.fact_type_id}"
|
318
318
|
nested_types <<
|
319
319
|
@by_id[id] =
|
320
|
-
nested_type = @constellation.EntityType(
|
320
|
+
nested_type = @constellation.EntityType(@vocabulary, name)
|
321
321
|
nested_type.fact_type = fact_type
|
322
322
|
end
|
323
323
|
}
|
@@ -390,7 +390,7 @@ module ActiveFacts
|
|
390
390
|
role.role_value_restriction = @constellation.ValueRestriction(:new)
|
391
391
|
x_ranges.each{|x_range|
|
392
392
|
v_range = value_range(x_range)
|
393
|
-
ar = @constellation.AllowedRange(
|
393
|
+
ar = @constellation.AllowedRange(role.role_value_restriction, v_range)
|
394
394
|
}
|
395
395
|
}
|
396
396
|
|
@@ -632,8 +632,8 @@ module ActiveFacts
|
|
632
632
|
# A TypeInheritance fact type has a uniqueness constraint on each role.
|
633
633
|
# If this UC is on the supertype and identifies the subtype, it's preferred:
|
634
634
|
is_supertype_constraint =
|
635
|
-
roles.all_role_ref.
|
636
|
-
(role =
|
635
|
+
(rr = roles.all_role_ref.single) &&
|
636
|
+
(role = rr.role) &&
|
637
637
|
(fact_type = role.fact_type) &&
|
638
638
|
fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance) &&
|
639
639
|
role.concept == fact_type.supertype &&
|
@@ -649,8 +649,7 @@ module ActiveFacts
|
|
649
649
|
pc.is_preferred_identifier = true if pi || unary_identifier || is_supertype_constraint
|
650
650
|
#puts "#{name} covers #{roles.describe} has min=#{pc.min_frequency}, max=1, preferred=#{pc.is_preferred_identifier.inspect}" if emit_special_debug
|
651
651
|
|
652
|
-
#puts roles.
|
653
|
-
#puts pc.verbalise
|
652
|
+
#puts roles.all_role_ref.to_a[0].role.fact_type.describe + " is subject to " + pc.describe if roles.all_role_ref.all?{|r| r.role.fact_type.is_a? ActiveFacts::Metamodel::TypeInheritance }
|
654
653
|
|
655
654
|
(@constraints_by_rs[roles] ||= []) << pc
|
656
655
|
}
|
@@ -3,8 +3,13 @@
|
|
3
3
|
#
|
4
4
|
# Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
|
5
5
|
#
|
6
|
+
|
7
|
+
# These files are concerned with calculating a relational schema for a vocabulary:
|
6
8
|
require 'activefacts/persistence/reference'
|
7
9
|
require 'activefacts/persistence/tables'
|
8
10
|
require 'activefacts/persistence/columns'
|
9
11
|
require 'activefacts/persistence/foreignkey'
|
10
12
|
require 'activefacts/persistence/index'
|
13
|
+
|
14
|
+
# These extend the API classes with relational awareness:
|
15
|
+
require 'activefacts/persistence/concept'
|