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.
- data/.gemtest +0 -0
- data/Manifest.txt +28 -33
- data/Rakefile +11 -12
- data/bin/cql +90 -46
- data/examples/CQL/Blog.cql +2 -1
- data/examples/CQL/CompanyDirectorEmployee.cql +2 -2
- data/examples/CQL/Death.cql +1 -1
- data/examples/CQL/Diplomacy.cql +9 -9
- data/examples/CQL/Genealogy.cql +3 -2
- data/examples/CQL/Insurance.cql +10 -7
- data/examples/CQL/JoinEquality.cql +2 -2
- data/examples/CQL/Marriage.cql +1 -1
- data/examples/CQL/Metamodel.cql +73 -53
- data/examples/CQL/MetamodelNext.cql +89 -67
- data/examples/CQL/OneToOnes.cql +2 -2
- data/examples/CQL/ServiceDirector.cql +10 -5
- data/examples/CQL/Supervision.cql +3 -3
- data/examples/CQL/Tests.Test5.Load.cql +1 -1
- data/examples/CQL/Warehousing.cql +4 -2
- data/lib/activefacts/cql/CQLParser.treetop +26 -60
- data/lib/activefacts/cql/Context.treetop +12 -2
- data/lib/activefacts/cql/Expressions.treetop +14 -30
- data/lib/activefacts/cql/FactTypes.treetop +165 -110
- data/lib/activefacts/cql/Language/English.treetop +167 -54
- data/lib/activefacts/cql/LexicalRules.treetop +16 -2
- data/lib/activefacts/cql/{Concepts.treetop → ObjectTypes.treetop} +36 -37
- data/lib/activefacts/cql/Terms.treetop +57 -27
- data/lib/activefacts/cql/ValueTypes.treetop +39 -13
- data/lib/activefacts/cql/compiler.rb +5 -3
- data/lib/activefacts/cql/compiler/{reading.rb → clause.rb} +407 -285
- data/lib/activefacts/cql/compiler/constraint.rb +178 -275
- data/lib/activefacts/cql/compiler/entity_type.rb +73 -64
- data/lib/activefacts/cql/compiler/expression.rb +418 -0
- data/lib/activefacts/cql/compiler/fact.rb +146 -145
- data/lib/activefacts/cql/compiler/fact_type.rb +197 -80
- data/lib/activefacts/cql/compiler/join.rb +159 -0
- data/lib/activefacts/cql/compiler/shared.rb +51 -23
- data/lib/activefacts/cql/compiler/value_type.rb +56 -2
- data/lib/activefacts/cql/parser.rb +15 -4
- data/lib/activefacts/generate/absorption.rb +7 -7
- data/lib/activefacts/generate/cql.rb +100 -37
- data/lib/activefacts/generate/oo.rb +28 -51
- data/lib/activefacts/generate/ordered.rb +60 -36
- data/lib/activefacts/generate/ruby.rb +6 -6
- data/lib/activefacts/generate/sql/server.rb +4 -4
- data/lib/activefacts/input/orm.rb +71 -53
- data/lib/activefacts/persistence.rb +1 -1
- data/lib/activefacts/persistence/columns.rb +27 -23
- data/lib/activefacts/persistence/foreignkey.rb +6 -6
- data/lib/activefacts/persistence/index.rb +17 -17
- data/lib/activefacts/persistence/{concept.rb → object_type.rb} +9 -9
- data/lib/activefacts/persistence/reference.rb +61 -36
- data/lib/activefacts/persistence/tables.rb +61 -59
- data/lib/activefacts/support.rb +54 -29
- data/lib/activefacts/version.rb +1 -1
- data/lib/activefacts/vocabulary/extensions.rb +99 -54
- data/lib/activefacts/vocabulary/metamodel.rb +43 -37
- data/lib/activefacts/vocabulary/verbaliser.rb +134 -109
- data/spec/absorption_spec.rb +8 -8
- data/spec/cql/comparison_spec.rb +91 -0
- data/spec/cql/contractions_spec.rb +251 -0
- data/spec/cql/entity_type_spec.rb +319 -0
- data/spec/cql/expressions_spec.rb +63 -0
- data/spec/cql/fact_type_matching_spec.rb +283 -0
- data/spec/cql/french_spec.rb +21 -0
- data/spec/cql/parser/bad_literals_spec.rb +86 -0
- data/spec/cql/parser/constraints_spec.rb +19 -0
- data/spec/cql/parser/entity_types_spec.rb +106 -0
- data/spec/cql/parser/expressions_spec.rb +179 -0
- data/spec/cql/parser/fact_types_spec.rb +41 -0
- data/spec/cql/parser/literals_spec.rb +312 -0
- data/spec/cql/parser/pragmas_spec.rb +89 -0
- data/spec/cql/parser/value_types_spec.rb +42 -0
- data/spec/cql/role_matching_spec.rb +147 -0
- data/spec/cql/samples_spec.rb +9 -9
- data/spec/cql_cql_spec.rb +1 -1
- data/spec/cql_dm_spec.rb +116 -0
- data/spec/cql_mysql_spec.rb +1 -1
- data/spec/cql_ruby_spec.rb +1 -1
- data/spec/cql_sql_spec.rb +3 -3
- data/spec/cql_symbol_tables_spec.rb +30 -30
- data/spec/cqldump_spec.rb +4 -4
- data/spec/helpers/array_matcher.rb +32 -27
- data/spec/helpers/diff_matcher.rb +6 -26
- data/spec/helpers/file_matcher.rb +41 -32
- data/spec/helpers/parse_to_ast_matcher.rb +76 -0
- data/spec/helpers/string_matcher.rb +32 -31
- data/spec/norma_cql_spec.rb +1 -1
- data/spec/norma_ruby_spec.rb +1 -1
- data/spec/norma_ruby_sql_spec.rb +1 -1
- data/spec/norma_sql_spec.rb +3 -1
- data/spec/norma_tables_spec.rb +1 -1
- data/spec/ruby_api_spec.rb +23 -0
- data/spec/spec_helper.rb +5 -4
- metadata +66 -66
- data/examples/CQL/OrienteeringER.cql +0 -58
- data/lib/activefacts/api.rb +0 -44
- data/lib/activefacts/api/concept.rb +0 -410
- data/lib/activefacts/api/constellation.rb +0 -128
- data/lib/activefacts/api/entity.rb +0 -256
- data/lib/activefacts/api/instance.rb +0 -60
- data/lib/activefacts/api/instance_index.rb +0 -80
- data/lib/activefacts/api/numeric.rb +0 -167
- data/lib/activefacts/api/role.rb +0 -80
- data/lib/activefacts/api/role_proxy.rb +0 -70
- data/lib/activefacts/api/role_values.rb +0 -117
- data/lib/activefacts/api/standard_types.rb +0 -87
- data/lib/activefacts/api/support.rb +0 -65
- data/lib/activefacts/api/value.rb +0 -135
- data/lib/activefacts/api/vocabulary.rb +0 -82
- data/spec/api/autocounter.rb +0 -82
- data/spec/api/constellation.rb +0 -130
- data/spec/api/entity_type.rb +0 -103
- data/spec/api/instance.rb +0 -461
- data/spec/api/roles.rb +0 -124
- data/spec/api/value_type.rb +0 -112
- data/spec/api_spec.rb +0 -13
- data/spec/cql/matching_spec.rb +0 -517
- data/spec/cql/unit_spec.rb +0 -394
- data/spec/spec.opts +0 -1
|
@@ -21,6 +21,7 @@ module ActiveFacts
|
|
|
21
21
|
def value_type_end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
# Dump the roles for an object type (excluding the roles of a fact type which is objectified)
|
|
24
25
|
def roles_dump(o)
|
|
25
26
|
o.all_role.
|
|
26
27
|
select{|role|
|
|
@@ -35,12 +36,14 @@ module ActiveFacts
|
|
|
35
36
|
end
|
|
36
37
|
|
|
37
38
|
def role_dump(role)
|
|
39
|
+
return if role.fact_type.entity_type
|
|
40
|
+
|
|
38
41
|
fact_type = role.fact_type
|
|
39
42
|
if fact_type.all_role.size == 1
|
|
40
|
-
unary_dump(role, preferred_role_name(role))
|
|
41
|
-
# REVISIT: If the objectified fact type has already been dumped, we'll get nothing.
|
|
43
|
+
unary_dump(role, preferred_role_name(role))
|
|
42
44
|
return
|
|
43
45
|
elsif fact_type.all_role.size != 2
|
|
46
|
+
# Shouldn't come here, except perhaps for an invalid model
|
|
44
47
|
return # ternaries and higher are always objectified
|
|
45
48
|
end
|
|
46
49
|
|
|
@@ -50,54 +53,28 @@ module ActiveFacts
|
|
|
50
53
|
return
|
|
51
54
|
end
|
|
52
55
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
return
|
|
64
|
-
end
|
|
56
|
+
return unless role.is_functional
|
|
57
|
+
|
|
58
|
+
other_role = fact_type.all_role.select{|r| r != role}[0]
|
|
59
|
+
other_role_name = preferred_role_name(other_role)
|
|
60
|
+
other_player = other_role.object_type
|
|
61
|
+
|
|
62
|
+
# It's a one_to_one if there's a uniqueness constraint on the other role:
|
|
63
|
+
one_to_one = other_role.is_functional
|
|
64
|
+
return if one_to_one &&
|
|
65
|
+
!@object_types_dumped[other_role.object_type]
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
other_role_method = role.concept.name.gsub(/ /,'_').snakecase
|
|
74
|
-
one_to_one = true
|
|
75
|
-
else
|
|
76
|
-
|
|
77
|
-
other_role = fact_type.all_role.select{|r| r != role}[0]
|
|
78
|
-
other_role_name = preferred_role_name(other_role)
|
|
79
|
-
other_player = other_role.concept
|
|
80
|
-
|
|
81
|
-
# It's a one_to_one if there's a uniqueness constraint on the other role:
|
|
82
|
-
one_to_one = ucs.find {|c| c.role_sequence.all_role_ref.map(&:role) == [other_role] }
|
|
83
|
-
if one_to_one &&
|
|
84
|
-
!@concept_types_dumped[other_role.concept]
|
|
85
|
-
#debug "Will dump 1:1 later for #{role} in #{fact_type}"
|
|
86
|
-
return
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
# Find role name:
|
|
90
|
-
role_method = preferred_role_name(role)
|
|
91
|
-
other_role_method = one_to_one ? role_method : "all_"+role_method
|
|
92
|
-
# puts "---"+role.role_name if role.role_name
|
|
93
|
-
if other_role_name != other_player.name.gsub(/ /,'_').snakecase and
|
|
94
|
-
role_method == role.concept.name.gsub(/ /,'_').snakecase
|
|
95
|
-
other_role_method += "_as_#{other_role_name}"
|
|
96
|
-
end
|
|
67
|
+
# Find role name:
|
|
68
|
+
role_method = preferred_role_name(role)
|
|
69
|
+
other_role_method = one_to_one ? role_method : "all_"+role_method
|
|
70
|
+
# puts "---"+role.role_name if role.role_name
|
|
71
|
+
if other_role_name != other_player.name.gsub(/ /,'_').snakecase and
|
|
72
|
+
role_method == role.object_type.name.gsub(/ /,'_').snakecase
|
|
73
|
+
other_role_method += "_as_#{other_role_name}"
|
|
97
74
|
end
|
|
98
75
|
|
|
99
76
|
role_name = role_method
|
|
100
|
-
role_name = nil if role_name == role.
|
|
77
|
+
role_name = nil if role_name == role.object_type.name.gsub(/ /,'_').snakecase
|
|
101
78
|
|
|
102
79
|
binary_dump(role, other_role_name, other_player, role.is_mandatory, one_to_one, nil, role_name, other_role_method)
|
|
103
80
|
end
|
|
@@ -106,7 +83,7 @@ module ActiveFacts
|
|
|
106
83
|
return "" if role.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
|
|
107
84
|
|
|
108
85
|
if is_for && role.fact_type.entity_type == is_for && role.fact_type.all_role.size == 1
|
|
109
|
-
return role.
|
|
86
|
+
return role.object_type.name.gsub(/[- ]/,'_').snakecase
|
|
110
87
|
end
|
|
111
88
|
|
|
112
89
|
# debug "Looking for preferred_role_name of #{describe_fact_type(role.fact_type, role)}"
|
|
@@ -121,7 +98,7 @@ module ActiveFacts
|
|
|
121
98
|
reading.text.gsub(/ *\{0\} */,'').gsub(/[- ]/,'_').downcase
|
|
122
99
|
end
|
|
123
100
|
|
|
124
|
-
# debug "\tleading_adjective=#{(p=preferred_role_ref).leading_adjective}, role_name=#{role.role_name}, role player=#{role.
|
|
101
|
+
# 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}"
|
|
125
102
|
role_words = []
|
|
126
103
|
role_name = role.role_name
|
|
127
104
|
role_name = nil if role_name == ""
|
|
@@ -130,7 +107,7 @@ module ActiveFacts
|
|
|
130
107
|
la = preferred_role_ref.leading_adjective
|
|
131
108
|
role_words << la.gsub(/ /,'_') if la && la != "" and !role.role_name
|
|
132
109
|
|
|
133
|
-
role_words << (role_name || role.
|
|
110
|
+
role_words << (role_name || role.object_type.name.gsub(/ /,'_'))
|
|
134
111
|
# REVISIT: Same when trailing_adjective is a suffix of the role_name
|
|
135
112
|
ta = preferred_role_ref.trailing_adjective
|
|
136
113
|
role_words << ta.gsub(/ /,'_') if ta && ta != "" and !role_name
|
|
@@ -157,12 +134,12 @@ module ActiveFacts
|
|
|
157
134
|
pc.max_frequency == 1
|
|
158
135
|
}
|
|
159
136
|
}
|
|
160
|
-
as = role_name != role.
|
|
137
|
+
as = role_name != role.object_type.name.gsub(/ /,'_').snakecase ? "_as_#{role_name}" : ""
|
|
161
138
|
raise "Fact #{fact_type.describe} type is not objectified" unless fact_type.entity_type
|
|
162
139
|
other_role_method = (one_to_one ? "" : "all_") +
|
|
163
140
|
fact_type.entity_type.name.gsub(/ /,'_').snakecase +
|
|
164
141
|
as
|
|
165
|
-
binary_dump(role, role_name, role.
|
|
142
|
+
binary_dump(role, role_name, role.object_type, true, one_to_one, nil, nil, other_role_method)
|
|
166
143
|
}
|
|
167
144
|
end
|
|
168
145
|
|
|
@@ -32,7 +32,7 @@ module ActiveFacts
|
|
|
32
32
|
vocabulary_start(@vocabulary)
|
|
33
33
|
|
|
34
34
|
build_indices
|
|
35
|
-
@
|
|
35
|
+
@object_types_dumped = {}
|
|
36
36
|
@fact_types_dumped = {}
|
|
37
37
|
units_dump()
|
|
38
38
|
value_types_dump()
|
|
@@ -67,35 +67,46 @@ module ActiveFacts
|
|
|
67
67
|
done_banner = false
|
|
68
68
|
units = @vocabulary.all_unit.to_a.sort_by{|u| u.name.gsub(/ /,'')}
|
|
69
69
|
while units.size > 0
|
|
70
|
-
if !done_banner
|
|
71
|
-
done_banner = true
|
|
72
|
-
units_banner
|
|
73
|
-
end
|
|
74
70
|
i = 0
|
|
75
71
|
while i < units.size
|
|
76
72
|
unit = units[i]
|
|
77
73
|
i += 1
|
|
74
|
+
|
|
78
75
|
# Skip this one if the precursors haven't yet been dumped:
|
|
79
76
|
next if unit.all_derivation_as_derived_unit.detect{|d| units.include?(d.base_unit) }
|
|
80
77
|
|
|
81
|
-
|
|
78
|
+
# Even if we skip, we're done with this unit
|
|
82
79
|
units.delete(unit)
|
|
83
80
|
i -= 1
|
|
81
|
+
|
|
82
|
+
# Skip value-type derived units
|
|
83
|
+
next if unit.name =~ /\^/
|
|
84
|
+
|
|
85
|
+
# Don't dump fundamental units which have normal derived units, they are implied:
|
|
86
|
+
next if unit.is_fundamental &&
|
|
87
|
+
unit.all_derivation_as_base_unit.detect{|d| d.derived_unit.name !~ /\^/}
|
|
88
|
+
|
|
89
|
+
if !done_banner
|
|
90
|
+
done_banner = true
|
|
91
|
+
units_banner
|
|
92
|
+
end
|
|
93
|
+
unit_dump(unit)
|
|
84
94
|
end
|
|
85
95
|
end
|
|
96
|
+
units_end if done_banner
|
|
86
97
|
end
|
|
87
98
|
|
|
88
99
|
def value_types_dump
|
|
89
100
|
done_banner = false
|
|
90
101
|
@value_type_dumped = {}
|
|
91
|
-
@vocabulary.
|
|
102
|
+
@vocabulary.all_object_type.sort_by{|o| o.name.gsub(/ /,'')}.each{|o|
|
|
92
103
|
next unless o.is_a?(ActiveFacts::Metamodel::ValueType)
|
|
93
104
|
|
|
94
105
|
value_type_banner unless done_banner
|
|
95
106
|
done_banner = true
|
|
96
107
|
|
|
97
108
|
value_type_chain_dump(o)
|
|
98
|
-
@
|
|
109
|
+
@object_types_dumped[o] = true
|
|
99
110
|
}
|
|
100
111
|
value_type_end if done_banner
|
|
101
112
|
end
|
|
@@ -116,7 +127,7 @@ module ActiveFacts
|
|
|
116
127
|
@precursors, @followers = *build_entity_dependencies
|
|
117
128
|
|
|
118
129
|
done_banner = false
|
|
119
|
-
sorted = @vocabulary.
|
|
130
|
+
sorted = @vocabulary.all_object_type.select{|o|
|
|
120
131
|
o.is_a?(ActiveFacts::Metamodel::EntityType) # and !o.fact_type
|
|
121
132
|
}.sort_by{|o| o.name.gsub(/ /,'')}
|
|
122
133
|
panic = nil
|
|
@@ -124,7 +135,7 @@ module ActiveFacts
|
|
|
124
135
|
count_this_pass = 0
|
|
125
136
|
skipped_this_pass = 0
|
|
126
137
|
sorted.each{|o|
|
|
127
|
-
next if @
|
|
138
|
+
next if @object_types_dumped[o] # Already done
|
|
128
139
|
|
|
129
140
|
# Can we do this yet?
|
|
130
141
|
if (o != panic and # We don't *have* to do it (panic mode)
|
|
@@ -160,7 +171,7 @@ module ActiveFacts
|
|
|
160
171
|
if panic # We were already panicing... what to do now?
|
|
161
172
|
# This won't happen again unless the above code is changed to decide it can't dump "panic".
|
|
162
173
|
raise "Unresolvable cycle of forward references: " +
|
|
163
|
-
(bad = sorted.select{|o| EntityType === o && !@
|
|
174
|
+
(bad = sorted.select{|o| EntityType === o && !@object_types_dumped[o]}).map{|o| o.name }.inspect +
|
|
164
175
|
":\n\t" + bad.map{|o|
|
|
165
176
|
o.name +
|
|
166
177
|
": " +
|
|
@@ -170,10 +181,10 @@ module ActiveFacts
|
|
|
170
181
|
# Find the object that has the most followers and no fwd-ref'd supertypes:
|
|
171
182
|
# This selection might be better if we allow PI roles to be fwd-ref'd...
|
|
172
183
|
panic = sorted.
|
|
173
|
-
select{|o| !@
|
|
184
|
+
select{|o| !@object_types_dumped[o] }.
|
|
174
185
|
sort_by{|o|
|
|
175
186
|
f = @followers[o] || [];
|
|
176
|
-
o.supertypes.detect{|s| !@
|
|
187
|
+
o.supertypes.detect{|s| !@object_types_dumped[s] } ? 0 : -f.size
|
|
177
188
|
}[0]
|
|
178
189
|
# debug "Panic mode, selected #{panic.name} next"
|
|
179
190
|
end
|
|
@@ -185,7 +196,7 @@ module ActiveFacts
|
|
|
185
196
|
end
|
|
186
197
|
|
|
187
198
|
def entity_type_dump(o)
|
|
188
|
-
@
|
|
199
|
+
@object_types_dumped[o] = true
|
|
189
200
|
pi = o.preferred_identifier
|
|
190
201
|
|
|
191
202
|
supers = o.supertypes
|
|
@@ -210,7 +221,6 @@ module ActiveFacts
|
|
|
210
221
|
identifying_facts = ([o.fact_type]+identifying_role_refs.map{|rr| rr.role.fact_type }).compact.uniq
|
|
211
222
|
|
|
212
223
|
identification = identified_by_roles_and_facts(o, identifying_role_refs, identifying_facts)
|
|
213
|
-
#identifying_facts.each{|f| @fact_types_dumped[f] = true }
|
|
214
224
|
|
|
215
225
|
identification
|
|
216
226
|
end
|
|
@@ -222,20 +232,20 @@ module ActiveFacts
|
|
|
222
232
|
|
|
223
233
|
def describe_roles(roles, highlight = nil)
|
|
224
234
|
"("+
|
|
225
|
-
roles.map{|role| role.
|
|
235
|
+
roles.map{|role| role.object_type.name + (role == highlight ? "*" : "")}*", "+
|
|
226
236
|
")"
|
|
227
237
|
end
|
|
228
238
|
|
|
229
239
|
def describe_role_sequence(role_sequence)
|
|
230
240
|
"("+
|
|
231
|
-
role_sequence.all_role_ref.map{|role_ref| role_ref.role.
|
|
241
|
+
role_sequence.all_role_ref.map{|role_ref| role_ref.role.object_type.name }*", "+
|
|
232
242
|
")"
|
|
233
243
|
end
|
|
234
244
|
|
|
235
245
|
# This returns an array of two hash tables each keyed by an EntityType.
|
|
236
246
|
# The values of each hash entry are the precursors and followers (respectively) of that entity.
|
|
237
247
|
def build_entity_dependencies
|
|
238
|
-
@vocabulary.
|
|
248
|
+
@vocabulary.all_object_type.inject([{},{}]) { |a, o|
|
|
239
249
|
if o.is_a?(ActiveFacts::Metamodel::EntityType)
|
|
240
250
|
precursor = a[0]
|
|
241
251
|
follower = a[1]
|
|
@@ -244,7 +254,7 @@ module ActiveFacts
|
|
|
244
254
|
if pi
|
|
245
255
|
pi.role_sequence.all_role_ref.each{|rr|
|
|
246
256
|
role = rr.role
|
|
247
|
-
player = role.
|
|
257
|
+
player = role.object_type
|
|
248
258
|
# REVISIT: If we decide to emit value types on demand, need to remove this:
|
|
249
259
|
next unless player.is_a?(ActiveFacts::Metamodel::EntityType)
|
|
250
260
|
# player is a precursor of o
|
|
@@ -254,9 +264,9 @@ module ActiveFacts
|
|
|
254
264
|
end
|
|
255
265
|
if o.fact_type
|
|
256
266
|
o.fact_type.all_role.each do |role|
|
|
257
|
-
next unless role.
|
|
258
|
-
(precursor[o] ||= []) << role.
|
|
259
|
-
(follower[role.
|
|
267
|
+
next unless role.object_type.is_a?(ActiveFacts::Metamodel::EntityType)
|
|
268
|
+
(precursor[o] ||= []) << role.object_type
|
|
269
|
+
(follower[role.object_type] ||= []) << o
|
|
260
270
|
end
|
|
261
271
|
end
|
|
262
272
|
|
|
@@ -289,9 +299,10 @@ module ActiveFacts
|
|
|
289
299
|
# The fact type hasn't already been dumped but all its role players have
|
|
290
300
|
!@fact_types_dumped[fact_type] &&
|
|
291
301
|
!fact_type.is_a?(ActiveFacts::Metamodel::ImplicitFactType) &&
|
|
292
|
-
!fact_type.all_role.detect{|r| !@
|
|
293
|
-
!fact_type.entity_type
|
|
294
|
-
|
|
302
|
+
!fact_type.all_role.detect{|r| !@object_types_dumped[r.object_type] } &&
|
|
303
|
+
!fact_type.entity_type &&
|
|
304
|
+
derivation_precursors_complete(fact_type)
|
|
305
|
+
# REVISIT: A derived fact type must not be dumped before its joined fact types have
|
|
295
306
|
}.sort_by{|fact_type|
|
|
296
307
|
fact_type_key(fact_type)
|
|
297
308
|
}.each{|fact_type|
|
|
@@ -303,12 +314,22 @@ module ActiveFacts
|
|
|
303
314
|
end while progress
|
|
304
315
|
end
|
|
305
316
|
|
|
317
|
+
def derivation_precursors_complete(fact_type)
|
|
318
|
+
pr = fact_type.preferred_reading
|
|
319
|
+
return true unless jr = pr.role_sequence.all_role_ref.to_a[0].join_role
|
|
320
|
+
join = jr.join_node.join
|
|
321
|
+
return false if join.all_join_step.detect{|js| !@fact_types_dumped[js.fact_type] }
|
|
322
|
+
return false if join.all_join_node.detect{|jn| !@object_types_dumped[jn.object_type] }
|
|
323
|
+
true
|
|
324
|
+
end
|
|
325
|
+
|
|
306
326
|
def skip_fact_type(f)
|
|
307
327
|
# REVISIT: There might be constraints we have to merge into the nested entity or subtype.
|
|
308
328
|
# These will come up as un-handled constraints:
|
|
309
329
|
pcs = @presence_constraints_by_fact[f]
|
|
310
|
-
f.is_a?(ActiveFacts::Metamodel::TypeInheritance)
|
|
311
|
-
|
|
330
|
+
return true if f.is_a?(ActiveFacts::Metamodel::TypeInheritance)
|
|
331
|
+
return false if f.entity_type && !@object_types_dumped[f.entity_type]
|
|
332
|
+
pcs && pcs.size > 0 && !pcs.detect{|c| !@constraints_used[c] }
|
|
312
333
|
end
|
|
313
334
|
|
|
314
335
|
# Dump one fact type.
|
|
@@ -341,7 +362,7 @@ module ActiveFacts
|
|
|
341
362
|
# REVISIT: Go through the residual constraints and re-process appropriate readings to show them
|
|
342
363
|
|
|
343
364
|
@fact_types_dumped[fact_type] = true
|
|
344
|
-
@
|
|
365
|
+
@object_types_dumped[fact_type.entity_type] = true if fact_type.entity_type
|
|
345
366
|
end
|
|
346
367
|
|
|
347
368
|
# Dump fact types.
|
|
@@ -360,7 +381,7 @@ module ActiveFacts
|
|
|
360
381
|
!fact_type.is_a?(ActiveFacts::Metamodel::ImplicitFactType) and
|
|
361
382
|
!@fact_types_dumped[fact_type] and
|
|
362
383
|
!skip_fact_type(fact_type) and
|
|
363
|
-
!fact_type.all_role.detect{|r| r.
|
|
384
|
+
!fact_type.all_role.detect{|r| r.object_type.is_a?(ActiveFacts::Metamodel::EntityType) }
|
|
364
385
|
}.sort_by{|fact_id|
|
|
365
386
|
fact_type = fact_collection[fact_id]
|
|
366
387
|
fact_type_key(fact_type)
|
|
@@ -380,7 +401,7 @@ module ActiveFacts
|
|
|
380
401
|
fact_type_key(fact_type)
|
|
381
402
|
}.each{|fact_type|
|
|
382
403
|
next if @fact_types_dumped[fact_type]
|
|
383
|
-
# debug "Not dumped #{fact_type.verbalise}(#{fact_type.all_role.map{|r| r.
|
|
404
|
+
# debug "Not dumped #{fact_type.verbalise}(#{fact_type.all_role.map{|r| r.object_type.name}*", "})"
|
|
384
405
|
fact_type_banner unless done_banner
|
|
385
406
|
done_banner = true
|
|
386
407
|
fact_type_dump_with_dependents(fact_type)
|
|
@@ -412,17 +433,17 @@ module ActiveFacts
|
|
|
412
433
|
pr.role_sequence.
|
|
413
434
|
all_role_ref.
|
|
414
435
|
sort_by{|role_ref| role_ref.ordinal}.
|
|
415
|
-
map{|role_ref| [ role_ref.leading_adjective, role_ref.role.
|
|
436
|
+
map{|role_ref| [ role_ref.leading_adjective, role_ref.role.object_type.name, role_ref.trailing_adjective ].compact*"-" } +
|
|
416
437
|
[pr.text]
|
|
417
438
|
else
|
|
418
|
-
fact_type.all_role.map{|role| role.
|
|
439
|
+
fact_type.all_role.map{|role| role.object_type.name }
|
|
419
440
|
end
|
|
420
441
|
|
|
421
442
|
(fact_type.entity_type ? [fact_type.entity_type.name] : [""]) + role_names
|
|
422
443
|
end
|
|
423
444
|
|
|
424
445
|
def role_ref_key(role_ref)
|
|
425
|
-
[ role_ref.leading_adjective, role_ref.role.
|
|
446
|
+
[ role_ref.leading_adjective, role_ref.role.object_type.name, role_ref.trailing_adjective ].compact*"-" +
|
|
426
447
|
" in " +
|
|
427
448
|
role_ref.role.fact_type.preferred_reading.expand
|
|
428
449
|
end
|
|
@@ -432,8 +453,8 @@ module ActiveFacts
|
|
|
432
453
|
when ActiveFacts::Metamodel::RingConstraint
|
|
433
454
|
[ 1,
|
|
434
455
|
c.ring_type,
|
|
435
|
-
c.role.
|
|
436
|
-
c.other_role.
|
|
456
|
+
c.role.object_type.name,
|
|
457
|
+
c.other_role.object_type.name,
|
|
437
458
|
c.name||""
|
|
438
459
|
]
|
|
439
460
|
when ActiveFacts::Metamodel::SetExclusionConstraint
|
|
@@ -499,7 +520,7 @@ module ActiveFacts
|
|
|
499
520
|
|
|
500
521
|
# Skip presence constraints on value types:
|
|
501
522
|
# next if ActiveFacts::PresenceConstraint === c &&
|
|
502
|
-
# ActiveFacts::ValueType === c.
|
|
523
|
+
# ActiveFacts::ValueType === c.object_type
|
|
503
524
|
constraint_dump(c)
|
|
504
525
|
end
|
|
505
526
|
constraint_end if heading
|
|
@@ -516,6 +537,9 @@ module ActiveFacts
|
|
|
516
537
|
def units_banner
|
|
517
538
|
end
|
|
518
539
|
|
|
540
|
+
def units_end
|
|
541
|
+
end
|
|
542
|
+
|
|
519
543
|
def unit_dump unit
|
|
520
544
|
end
|
|
521
545
|
|
|
@@ -145,11 +145,11 @@ module ActiveFacts
|
|
|
145
145
|
|
|
146
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)
|
|
147
147
|
# Find whether we need the name of the other role player, and whether it's defined yet:
|
|
148
|
-
if role_name.camelcase
|
|
148
|
+
if role_name.camelcase == role_player.name.gsub(/ /,'').sub(/^[a-z]/) {|i| i.upcase}
|
|
149
149
|
# Don't use Class name if implied by rolename
|
|
150
150
|
role_reference = nil
|
|
151
151
|
else
|
|
152
|
-
role_reference = ":class => "+
|
|
152
|
+
role_reference = ":class => "+object_type_reference(role_player)
|
|
153
153
|
end
|
|
154
154
|
other_role_name = ":counterpart => :"+other_role_name.gsub(/ /,'_') if other_role_name
|
|
155
155
|
|
|
@@ -167,11 +167,11 @@ module ActiveFacts
|
|
|
167
167
|
#puts " \# REVISIT: #{other_role_name} has values restricted to #{role.role_value_constraint}\n" if role.role_value_constraint
|
|
168
168
|
end
|
|
169
169
|
|
|
170
|
-
def
|
|
171
|
-
if !@
|
|
172
|
-
'"'+
|
|
170
|
+
def object_type_reference object_type
|
|
171
|
+
if !@object_types_dumped[object_type]
|
|
172
|
+
'"'+object_type.name.gsub(/ /,'')+'"'
|
|
173
173
|
else
|
|
174
|
-
role_reference =
|
|
174
|
+
role_reference = object_type.name.gsub(/ /,'')
|
|
175
175
|
end
|
|
176
176
|
end
|
|
177
177
|
|
|
@@ -134,7 +134,7 @@ module ActiveFacts
|
|
|
134
134
|
delayed_foreign_keys = []
|
|
135
135
|
|
|
136
136
|
@vocabulary.tables.each do |table|
|
|
137
|
-
puts "CREATE TABLE #{escape table.name
|
|
137
|
+
puts "CREATE TABLE #{escape table.name.gsub(' ',@underscore)} ("
|
|
138
138
|
|
|
139
139
|
pk = table.identifier_columns
|
|
140
140
|
identity_column = pk[0] if pk.size == 1 && pk[0].is_auto_assigned
|
|
@@ -178,7 +178,7 @@ module ActiveFacts
|
|
|
178
178
|
table.foreign_keys.each do |fk|
|
|
179
179
|
fk_text = "FOREIGN KEY (" +
|
|
180
180
|
fk.from_columns.map{|column| column.name(@underscore)}*", " +
|
|
181
|
-
") REFERENCES #{escape fk.to.name
|
|
181
|
+
") REFERENCES #{escape fk.to.name.gsub(' ',@underscore)} (" +
|
|
182
182
|
fk.to_columns.map{|column| column.name(@underscore)}*", " +
|
|
183
183
|
")"
|
|
184
184
|
if !@delay_fks and # We don't want to delay all Fks
|
|
@@ -186,7 +186,7 @@ module ActiveFacts
|
|
|
186
186
|
fk.to == table && !fk.to_columns.detect{|column| !column.is_mandatory}) # The reference columns already have the required indexes
|
|
187
187
|
inline_fks << fk_text
|
|
188
188
|
else
|
|
189
|
-
delayed_foreign_keys << ("ALTER TABLE #{escape fk.from.name
|
|
189
|
+
delayed_foreign_keys << ("ALTER TABLE #{escape fk.from.name.gsub(' ',@underscore)}\n\tADD " + fk_text)
|
|
190
190
|
end
|
|
191
191
|
end
|
|
192
192
|
|
|
@@ -204,7 +204,7 @@ module ActiveFacts
|
|
|
204
204
|
view_name = escape "#{index.view_name}_#{abbreviated_column_names}"
|
|
205
205
|
delayed_indices <<
|
|
206
206
|
%Q{CREATE VIEW dbo.#{view_name} (#{column_name_list}) WITH SCHEMABINDING AS
|
|
207
|
-
\tSELECT #{column_name_list} FROM dbo.#{escape index.on.name
|
|
207
|
+
\tSELECT #{column_name_list} FROM dbo.#{escape index.on.name.gsub(' ',@underscore)}
|
|
208
208
|
\tWHERE\t#{
|
|
209
209
|
index.columns.
|
|
210
210
|
select{|column| !column.is_mandatory }.
|