activefacts 0.8.18 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/Rakefile +0 -8
- data/examples/CQL/CompanyDirectorEmployee.cql +12 -8
- data/examples/CQL/Metamodel.cql +40 -24
- data/examples/CQL/OilSupply.cql +10 -8
- data/examples/CQL/unit.cql +52 -51
- data/lib/activefacts/cql/LexicalRules.treetop +1 -1
- data/lib/activefacts/cql/compiler.rb +1 -1
- data/lib/activefacts/cql/compiler/clause.rb +16 -24
- data/lib/activefacts/cql/compiler/constraint.rb +4 -4
- data/lib/activefacts/cql/compiler/entity_type.rb +16 -16
- data/lib/activefacts/cql/compiler/expression.rb +3 -3
- data/lib/activefacts/cql/compiler/fact.rb +1 -1
- data/lib/activefacts/cql/compiler/fact_type.rb +14 -4
- data/lib/activefacts/cql/compiler/shared.rb +1 -1
- data/lib/activefacts/cql/compiler/value_type.rb +2 -2
- data/lib/activefacts/generate/cql.rb +10 -34
- data/lib/activefacts/generate/helpers/oo.rb +10 -6
- data/lib/activefacts/generate/helpers/ordered.rb +32 -6
- data/lib/activefacts/generate/json.rb +2 -2
- data/lib/activefacts/generate/ruby.rb +7 -15
- data/lib/activefacts/generate/transform/surrogate.rb +7 -7
- data/lib/activefacts/input/orm.rb +23 -26
- data/lib/activefacts/persistence/index.rb +1 -1
- data/lib/activefacts/persistence/reference.rb +5 -2
- data/lib/activefacts/version.rb +3 -3
- data/lib/activefacts/vocabulary/extensions.rb +59 -19
- data/lib/activefacts/vocabulary/metamodel.rb +30 -14
- data/spec/cql/parser/bad_literals_spec.rb +1 -1
- data/spec/cql/parser/expressions_spec.rb +1 -1
- data/spec/cql_dm_spec.rb +15 -0
- data/spec/cql_mysql_spec.rb +1 -1
- data/spec/cqldump_spec.rb +12 -12
- data/spec/norma_cql_spec.rb +0 -1
- data/spec/norma_ruby_sql_spec.rb +3 -2
- data/spec/norma_tables_spec.rb +1 -1
- metadata +78 -127
- data/examples/CQL/JoinEquality.cql +0 -35
- data/examples/CQL/MonthInSeason.cql +0 -23
- data/examples/CQL/Moon.cql +0 -23
- data/examples/CQL/SubtypePI.cql +0 -31
- data/examples/CQL/Tests.Test5.Load.cql +0 -38
@@ -52,7 +52,7 @@ module ActiveFacts
|
|
52
52
|
when ActiveFacts::Metamodel::PresenceConstraint
|
53
53
|
fact_types = c.role_sequence.all_role_ref.map{|rr| rr.role.fact_type}.uniq # All fact types spanned by this constraint
|
54
54
|
if fact_types.size == 1 # There's only one, save it:
|
55
|
-
# debug "Single-fact constraint on #{fact_types[0].guid}: #{c.name}"
|
55
|
+
# debug "Single-fact constraint on #{fact_types[0].concept.guid}: #{c.name}"
|
56
56
|
(@presence_constraints_by_fact[fact_types[0]] ||= []) << c
|
57
57
|
end
|
58
58
|
when ActiveFacts::Metamodel::RingConstraint
|
@@ -93,6 +93,26 @@ module ActiveFacts
|
|
93
93
|
units_end if done_banner
|
94
94
|
end
|
95
95
|
|
96
|
+
def value_type_fork(o)
|
97
|
+
if o.name == "_ImplicitBooleanValueType"
|
98
|
+
# do nothing
|
99
|
+
elsif
|
100
|
+
!o.supertype # No supertype, i.e. a base type
|
101
|
+
o.all_role.size == 0 && # No roles
|
102
|
+
!o.is_independent && # not independent
|
103
|
+
!o.value_constraint && # No value constraints
|
104
|
+
o.concept.all_context_note_as_relevant_concept.size == 0 && # No context notes
|
105
|
+
o.all_instance.size == 0 # No instances
|
106
|
+
data_type_dump(o)
|
107
|
+
else
|
108
|
+
super_type_name = o.supertype ? o.supertype.name : o.name
|
109
|
+
length = (l = o.length) && l > 0 ? "#{l}" : nil
|
110
|
+
scale = (s = o.scale) && s > 0 ? "#{s}" : nil
|
111
|
+
facets = { :length => length, :scale => scale }
|
112
|
+
value_type_dump(o, super_type_name, facets)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
96
116
|
def value_types_dump
|
97
117
|
done_banner = false
|
98
118
|
@value_type_dumped = {}
|
@@ -112,7 +132,7 @@ module ActiveFacts
|
|
112
132
|
def value_type_chain_dump(o)
|
113
133
|
return if @value_type_dumped[o]
|
114
134
|
value_type_chain_dump(o.supertype) if (o.supertype && !@value_type_dumped[o.supertype])
|
115
|
-
|
135
|
+
value_type_fork(o)
|
116
136
|
@value_type_dumped[o] = true
|
117
137
|
end
|
118
138
|
|
@@ -306,11 +326,13 @@ module ActiveFacts
|
|
306
326
|
end
|
307
327
|
|
308
328
|
def skip_fact_type(f)
|
329
|
+
return true if f.is_a?(ActiveFacts::Metamodel::TypeInheritance)
|
330
|
+
return false if f.entity_type && !@object_types_dumped[f.entity_type]
|
331
|
+
|
309
332
|
# REVISIT: There might be constraints we have to merge into the nested entity or subtype.
|
310
333
|
# These will come up as un-handled constraints:
|
334
|
+
# Dump this fact type only if it contains a presence constraint we've missed:
|
311
335
|
pcs = @presence_constraints_by_fact[f]
|
312
|
-
return true if f.is_a?(ActiveFacts::Metamodel::TypeInheritance)
|
313
|
-
return false if f.entity_type && !@object_types_dumped[f.entity_type]
|
314
336
|
pcs && pcs.size > 0 && !pcs.detect{|c| !@constraints_used[c] }
|
315
337
|
end
|
316
338
|
|
@@ -334,7 +356,7 @@ module ActiveFacts
|
|
334
356
|
|
335
357
|
# debug "for fact type #{fact_type.to_s}, considering\n\t#{fact_constraints.map(&:to_s)*",\n\t"}"
|
336
358
|
# debug "#{fact_type.name} has readings:\n\t#{fact_type.readings.map(&:name)*"\n\t"}"
|
337
|
-
# debug "Dumping #{fact_type.guid} as a fact type"
|
359
|
+
# debug "Dumping #{fact_type.concept.guid} as a fact type"
|
338
360
|
|
339
361
|
# Fact types that aren't nested have no names
|
340
362
|
name = fact_type.entity_type && fact_type.entity_type.name
|
@@ -531,7 +553,11 @@ module ActiveFacts
|
|
531
553
|
debug "Should override value_type_end"
|
532
554
|
end
|
533
555
|
|
534
|
-
def
|
556
|
+
def data_type_dump(o)
|
557
|
+
debug "Should override data_type_dump"
|
558
|
+
end
|
559
|
+
|
560
|
+
def value_type_dump(o, super_type_name, facets)
|
535
561
|
debug "Should override value_type_dump"
|
536
562
|
end
|
537
563
|
|
@@ -72,7 +72,7 @@ module ActiveFacts
|
|
72
72
|
if o.fact_type
|
73
73
|
uuid = (uuids[o.fact_type] ||= uuid_from_id(o.fact_type))
|
74
74
|
j[:objectifies] = uuid
|
75
|
-
j[:implicit] = true if o.
|
75
|
+
j[:implicit] = true if o.concept.implication_rule
|
76
76
|
end
|
77
77
|
if o.all_type_inheritance_as_subtype.size > 0
|
78
78
|
j[:supertypes] = o.
|
@@ -248,7 +248,7 @@ module ActiveFacts
|
|
248
248
|
if (c.enforcement)
|
249
249
|
# REVISIT: Deontic constraint
|
250
250
|
end
|
251
|
-
if (c.all_context_note_as_relevant_concept.size > 0)
|
251
|
+
if (c.concept.all_context_note_as_relevant_concept.size > 0)
|
252
252
|
# REVISIT: Context Notes
|
253
253
|
end
|
254
254
|
|
@@ -59,25 +59,17 @@ module ActiveFacts
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
def
|
62
|
+
def data_type_dump(o)
|
63
|
+
value_type_dump(o, o.name, {}) if o.all_role.size > 0
|
64
|
+
end
|
65
|
+
|
66
|
+
def value_type_dump(o, super_type_name, facets)
|
63
67
|
length = (l = o.length) && l > 0 ? ":length => #{l}" : nil
|
64
68
|
scale = (s = o.scale) && s > 0 ? ":scale => #{s}" : nil
|
65
69
|
params = [length,scale].compact * ", "
|
66
70
|
|
67
|
-
|
68
|
-
|
69
|
-
o.all_role.size == 0 && # No roles
|
70
|
-
!o.is_independent && # not independent
|
71
|
-
o.all_instance.size == 0 # No instances
|
72
|
-
|
73
|
-
name = o.name
|
74
|
-
ruby_type_name =
|
75
|
-
if o.supertype
|
76
|
-
o.supertype.name.gsub(/ /,'')
|
77
|
-
else
|
78
|
-
o.name.gsub(/ /,'')
|
79
|
-
end
|
80
|
-
name = name.sub(/^[a-z]/) {|i| i.upcase}.gsub(/ /,'')
|
71
|
+
ruby_type_name = super_type_name.gsub(/ /,'')
|
72
|
+
name = o.name.sub(/^[a-z]/) {|i| i.upcase}.gsub(/ /,'')
|
81
73
|
if ruby_type_name == name
|
82
74
|
ruby_type_name = '::'+ruby_type_name
|
83
75
|
end
|
@@ -14,18 +14,18 @@ module ActiveFacts
|
|
14
14
|
def add_surrogate type_name = 'Auto Counter', suffix = 'ID'
|
15
15
|
# Find or assert the surrogate value type
|
16
16
|
auto_counter = vocabulary.valid_value_type_name(type_name) ||
|
17
|
-
constellation.ValueType(:vocabulary => vocabulary, :name => type_name, :
|
17
|
+
constellation.ValueType(:vocabulary => vocabulary, :name => type_name, :concept => :new)
|
18
18
|
|
19
19
|
# Create a subtype to identify this entity type:
|
20
20
|
vt_name = self.name + ' '+suffix
|
21
21
|
my_id = @vocabulary.valid_value_type_name(vt_name) ||
|
22
|
-
constellation.ValueType(:vocabulary => vocabulary, :name => vt_name, :
|
22
|
+
constellation.ValueType(:vocabulary => vocabulary, :name => vt_name, :concept => :new, :supertype => auto_counter)
|
23
23
|
|
24
24
|
# Create a fact type
|
25
|
-
identifying_fact_type = constellation.FactType(:
|
26
|
-
my_role = constellation.Role(:
|
25
|
+
identifying_fact_type = constellation.FactType(:concept => :new)
|
26
|
+
my_role = constellation.Role(:concept => :new, :fact_type => identifying_fact_type, :ordinal => 0, :object_type => self)
|
27
27
|
@injected_surrogate_role = my_role
|
28
|
-
id_role = constellation.Role(:
|
28
|
+
id_role = constellation.Role(:concept => :new, :fact_type => identifying_fact_type, :ordinal => 1, :object_type => my_id)
|
29
29
|
|
30
30
|
# Create a reading (which needs a RoleSequence)
|
31
31
|
reading = constellation.Reading(
|
@@ -39,7 +39,7 @@ module ActiveFacts
|
|
39
39
|
|
40
40
|
# Create two uniqueness constraints for the one-to-one. Each needs a RoleSequence (two RoleRefs)
|
41
41
|
one_id = constellation.PresenceConstraint(
|
42
|
-
:
|
42
|
+
:concept => :new,
|
43
43
|
:vocabulary => vocabulary,
|
44
44
|
:name => self.name+'HasOne'+suffix,
|
45
45
|
:role_sequence => [:new],
|
@@ -51,7 +51,7 @@ module ActiveFacts
|
|
51
51
|
@constellation.RoleRef(:role_sequence => one_id.role_sequence, :ordinal => 0, :role => my_role)
|
52
52
|
|
53
53
|
one_me = constellation.PresenceConstraint(
|
54
|
-
:
|
54
|
+
:concept => :new,
|
55
55
|
:vocabulary => vocabulary,
|
56
56
|
:name => self.name+suffix+'IsOfOne'+self.name,
|
57
57
|
:role_sequence => [:new],
|
@@ -48,8 +48,8 @@ module ActiveFacts
|
|
48
48
|
"UnsignedLargeIntegerNumeric" => "Unsigned Integer(64)",
|
49
49
|
"AutoCounterNumeric" => "Auto Counter",
|
50
50
|
"FloatingPointNumeric" => "Real(64)",
|
51
|
-
"SinglePrecisionFloatingPointNumeric" => "
|
52
|
-
"DoublePrecisionFloatingPointNumeric" => "
|
51
|
+
"SinglePrecisionFloatingPointNumeric" => "Real(32)",
|
52
|
+
"DoublePrecisionFloatingPointNumeric" => "Real(32)",
|
53
53
|
"DecimalNumeric" => "Decimal",
|
54
54
|
"MoneyNumeric" => "Money",
|
55
55
|
"FixedLengthRawData" => "Blob",
|
@@ -160,7 +160,7 @@ module ActiveFacts
|
|
160
160
|
@by_id[id] =
|
161
161
|
debug :orm, "Asserting new EntityType #{name.inspect}" do
|
162
162
|
@vocabulary.valid_entity_type_name(name) ||
|
163
|
-
@constellation.EntityType(@vocabulary, name, :
|
163
|
+
@constellation.EntityType(@vocabulary, name, :concept => id_of(x))
|
164
164
|
end
|
165
165
|
entity_types << entity_type
|
166
166
|
independent = x['IsIndependent']
|
@@ -233,7 +233,7 @@ module ActiveFacts
|
|
233
233
|
debug :orm, "Asserting new ValueType #{supertype_name.inspect} for supertype" do
|
234
234
|
value_super_type =
|
235
235
|
@vocabulary.valid_value_type_name(supertype_name) ||
|
236
|
-
@constellation.ValueType(@vocabulary, supertype_name, :
|
236
|
+
@constellation.ValueType(@vocabulary, supertype_name, :concept => id_of(x_supertype))
|
237
237
|
end
|
238
238
|
else
|
239
239
|
# REVISIT: Need to handle standard types better here:
|
@@ -241,7 +241,7 @@ module ActiveFacts
|
|
241
241
|
if type_name != name
|
242
242
|
debug :orm, "Asserting new ValueType #{type_name.inspect} for supertype" do
|
243
243
|
@vocabulary.valid_value_type_name(type_name) ||
|
244
|
-
@constellation.ValueType(@vocabulary.identifying_role_values, type_name, :
|
244
|
+
@constellation.ValueType(@vocabulary.identifying_role_values, type_name, :concept => :new)
|
245
245
|
end
|
246
246
|
else
|
247
247
|
nil
|
@@ -252,7 +252,7 @@ module ActiveFacts
|
|
252
252
|
debug :orm, "Asserting new ValueType #{name.inspect}" do
|
253
253
|
@by_id[id] =
|
254
254
|
@vocabulary.valid_value_type_name(name) ||
|
255
|
-
@constellation.ValueType(@vocabulary.identifying_role_values, name, :
|
255
|
+
@constellation.ValueType(@vocabulary.identifying_role_values, name, :concept => id_of(x))
|
256
256
|
end
|
257
257
|
vt.supertype = value_super_type
|
258
258
|
vt.length = length if length
|
@@ -305,7 +305,6 @@ module ActiveFacts
|
|
305
305
|
name = "<unnamed>" if !name
|
306
306
|
name = "" if !name || name.size == 0
|
307
307
|
# Note that the new metamodel doesn't have a name for a facttype unless it's objectified
|
308
|
-
next if x.xpath("orm:DerivationRule").size > 0
|
309
308
|
|
310
309
|
debug :orm, "FactType #{name || id}"
|
311
310
|
facts << @by_id[id] = fact_type = @constellation.FactType(id_of(x))
|
@@ -353,7 +352,7 @@ module ActiveFacts
|
|
353
352
|
next if subtype.kind_of? ActiveFacts::Metamodel::ValueType or
|
354
353
|
supertype.kind_of? ActiveFacts::Metamodel::ValueType
|
355
354
|
|
356
|
-
inheritance_fact = @constellation.TypeInheritance(subtype, supertype, :
|
355
|
+
inheritance_fact = @constellation.TypeInheritance(subtype, supertype, :concept => id_of(x))
|
357
356
|
if x["IsPrimary"] == "true" or # Old way
|
358
357
|
x["PreferredIdentificationPath"] == "true" # Newer
|
359
358
|
debug :orm, "#{supertype.name} is primary supertype of #{subtype.name}"
|
@@ -365,8 +364,8 @@ module ActiveFacts
|
|
365
364
|
facts << @by_id[id] = inheritance_fact
|
366
365
|
|
367
366
|
# Create the new Roles so we can find constraints on them:
|
368
|
-
subtype_role = @by_id[subtype_role_id] = @constellation.Role(inheritance_fact, 0, :object_type => subtype, :
|
369
|
-
supertype_role = @by_id[supertype_role_id] = @constellation.Role(inheritance_fact, 1, :object_type => supertype, :
|
367
|
+
subtype_role = @by_id[subtype_role_id] = @constellation.Role(inheritance_fact, 0, :object_type => subtype, :concept => id_of(x_subtype_role))
|
368
|
+
supertype_role = @by_id[supertype_role_id] = @constellation.Role(inheritance_fact, 1, :object_type => supertype, :concept => id_of(x_supertype_role))
|
370
369
|
|
371
370
|
# Create readings, so constraints can be verbalised for example:
|
372
371
|
rs = @constellation.RoleSequence(:new)
|
@@ -402,17 +401,16 @@ module ActiveFacts
|
|
402
401
|
|
403
402
|
fact_id = x_fact_type['ref']
|
404
403
|
fact_type = @by_id[fact_id]
|
405
|
-
next if x.xpath("orm:DerivationRule").size > 0
|
406
404
|
next unless fact_type # "Nested fact #{fact_id} not found; objectification of a derived fact type?"
|
407
405
|
|
408
|
-
debug :orm, "NestedType #{name} is #{id}, nests #{fact_type.guid}"
|
406
|
+
debug :orm, "NestedType #{name} is #{id}, nests #{fact_type.concept.guid}"
|
409
407
|
@nested_types <<
|
410
408
|
@by_id[id] =
|
411
409
|
nested_type = @vocabulary.valid_entity_type_name(name) ||
|
412
|
-
@constellation.EntityType(@vocabulary, name, :
|
410
|
+
@constellation.EntityType(@vocabulary, name, :concept => id_of(x))
|
413
411
|
independent = x['IsIndependent']
|
414
412
|
nested_type.is_independent = true if independent && independent == 'true' && !is_implied
|
415
|
-
nested_type.
|
413
|
+
nested_type.concept.implication_rule = 'objectification' if is_implied
|
416
414
|
nested_type.fact_type = fact_type
|
417
415
|
}
|
418
416
|
end
|
@@ -431,7 +429,6 @@ module ActiveFacts
|
|
431
429
|
debug :orm, "Reading roles and readings" do
|
432
430
|
@x_facts.each{|x|
|
433
431
|
id = x['id']
|
434
|
-
next if x.xpath("orm:DerivationRule").size > 0
|
435
432
|
fact_type = @by_id[id]
|
436
433
|
fact_name = x['Name'] || x['_Name'] || ''
|
437
434
|
#fact_name.gsub!(/\s/,'')
|
@@ -475,16 +472,18 @@ module ActiveFacts
|
|
475
472
|
@by_id.delete(ref) # and de-index it from our list
|
476
473
|
next
|
477
474
|
end
|
478
|
-
|
475
|
+
if !object_type
|
476
|
+
throw "RolePlayer for '#{name}' #{ref} in fact type #{x.parent.parent['_Name']} was not found"
|
477
|
+
end
|
479
478
|
|
480
479
|
debug :orm, "#{@vocabulary.name}, RoleName=#{x['Name'].inspect} played by object_type=#{object_type.name}"
|
481
480
|
throw "Role is played by #{object_type.class} not ObjectType" if !(@constellation.vocabulary.object_type(:ObjectType) === object_type)
|
482
481
|
|
483
|
-
debug :orm, "Creating role #{name} nr#{fact_type.all_role.size} of #{fact_type.guid} played by #{object_type.name}"
|
482
|
+
debug :orm, "Creating role #{name} nr#{fact_type.all_role.size} of #{fact_type.concept.guid} played by #{object_type.name}"
|
484
483
|
|
485
|
-
role = @by_id[id] = @constellation.Role(fact_type, fact_type.all_role.size, :object_type => object_type, :
|
484
|
+
role = @by_id[id] = @constellation.Role(fact_type, fact_type.all_role.size, :object_type => object_type, :concept => id_of(x))
|
486
485
|
role.role_name = name if name && name != object_type.name
|
487
|
-
debug :orm, "Fact #{fact_name} (id #{fact_type.guid
|
486
|
+
debug :orm, "Fact #{fact_name} (id #{fact_type.concept.guid}) role #{x['Name']} is played by #{object_type.name}, role is #{role.concept.guid}"
|
488
487
|
|
489
488
|
x_vr = x.xpath("orm:ValueRestriction/orm:RoleValueConstraint")
|
490
489
|
x_vr.each{|vr|
|
@@ -571,7 +570,7 @@ module ActiveFacts
|
|
571
570
|
text.strip!
|
572
571
|
text.downcase! # Check for reserved words and object type names *after* downcasing
|
573
572
|
elided = ''
|
574
|
-
text.gsub!(/(
|
573
|
+
text.gsub!(/( |[a-z]+(-[a-z]+)+|-?\b[A-Za-z_][A-Za-z0-9_]*\b-?|\{\d\})|./) do |w|
|
575
574
|
case w
|
576
575
|
when /[A-Za-z]/
|
577
576
|
if RESERVED_WORDS.include?(w)
|
@@ -599,7 +598,7 @@ module ActiveFacts
|
|
599
598
|
end
|
600
599
|
|
601
600
|
def get_role_sequence(role_array)
|
602
|
-
# puts "Getting RoleSequence [#{role_array.map{|r| "#{r.object_type.name} (role #{r.
|
601
|
+
# puts "Getting RoleSequence [#{role_array.map{|r| "#{r.object_type.name} (role #{r.concept.guid})" }*", "}]"
|
603
602
|
|
604
603
|
# Look for an existing RoleSequence
|
605
604
|
# REVISIT: This searches all role sequences. Perhaps we could narrow it down first instead?
|
@@ -640,8 +639,6 @@ module ActiveFacts
|
|
640
639
|
# This might have been a role of an ImpliedFact, which makes it safe to ignore.
|
641
640
|
next if 'ImpliedFact' == x_role.parent.parent.name
|
642
641
|
|
643
|
-
next if x_role.parent.parent.xpath('orm:DerivationRule').size > 0
|
644
|
-
|
645
642
|
# Talk about why this wasn't found - this shouldn't happen.
|
646
643
|
if (!x_nests || !implied)
|
647
644
|
#puts "="*60
|
@@ -1236,7 +1233,7 @@ module ActiveFacts
|
|
1236
1233
|
|
1237
1234
|
def read_instances
|
1238
1235
|
debug :orm, "Reading sample data" do
|
1239
|
-
population = @constellation.Population(@vocabulary, "sample", :
|
1236
|
+
population = @constellation.Population(@vocabulary, "sample", :concept => :new)
|
1240
1237
|
|
1241
1238
|
# Value instances first, then entities then facts:
|
1242
1239
|
|
@@ -1406,7 +1403,7 @@ module ActiveFacts
|
|
1406
1403
|
:guid => id_of(x_shape), :orm_diagram => diagram, :location => location, :is_expanded => is_expanded,
|
1407
1404
|
:constraint => subject
|
1408
1405
|
)
|
1409
|
-
shape.
|
1406
|
+
shape.fact_type_shape = subject.role.fact_type.all_fact_type_shape.to_a[0]
|
1410
1407
|
when 'ModelNoteShape'
|
1411
1408
|
# REVISIT: Add model notes
|
1412
1409
|
when 'ObjectTypeShape'
|
@@ -1445,7 +1442,7 @@ module ActiveFacts
|
|
1445
1442
|
offs_y = -12
|
1446
1443
|
if fact_type.entity_type
|
1447
1444
|
offs_x -= 12
|
1448
|
-
offs_y -= 9 if !fact_type.entity_type.
|
1445
|
+
offs_y -= 9 if !fact_type.entity_type.concept.implication_rule # .implication_rule_name == 'objectification'
|
1449
1446
|
end
|
1450
1447
|
|
1451
1448
|
location = convert_location(bounds, Gravity::S, offs_x, offs_y)
|
@@ -173,7 +173,7 @@ module ActiveFacts
|
|
173
173
|
|
174
174
|
debug :index, "All Indices in #{name}:" do
|
175
175
|
@indices = columns_by_unique_constraint.map do |uc, columns_with_ordinal|
|
176
|
-
debug :index, "Index due to uc #{uc.guid} on #{name} over (#{columns_with_ordinal.sort_by{|onc|onc[0]}.map{|ca| ca[2].name}.inspect})"
|
176
|
+
debug :index, "Index due to uc #{uc.concept.guid} on #{name} over (#{columns_with_ordinal.sort_by{|onc|onc[0]}.map{|ca| ca[2].name}.inspect})"
|
177
177
|
columns = columns_with_ordinal.sort_by{|ca| [ca[0,2], ca[2].name]}.map{|ca| ca[2]}
|
178
178
|
absorption_level = columns.map(&:absorption_level).min
|
179
179
|
over = columns[0].references[absorption_level].from
|
@@ -217,7 +217,7 @@ module ActiveFacts
|
|
217
217
|
end
|
218
218
|
|
219
219
|
module Metamodel #:nodoc:
|
220
|
-
class ObjectType
|
220
|
+
class ObjectType
|
221
221
|
# Say whether the independence of this object is still under consideration
|
222
222
|
# This is used in detecting dependency cycles, such as occurs in the Metamodel
|
223
223
|
attr_accessor :tentative #:nodoc:
|
@@ -273,7 +273,10 @@ module ActiveFacts
|
|
273
273
|
all_role.each do |role|
|
274
274
|
# It's possible that this role is in an implicit or derived fact type. Skip it if so.
|
275
275
|
next if role.fact_type.is_a?(LinkFactType) or
|
276
|
-
|
276
|
+
# REVISIT: dafuq? Is this looking for a constraint over a derivation? This looks wrong.
|
277
|
+
role.fact_type.preferred_reading.role_sequence.all_role_ref.to_a[0].play or
|
278
|
+
# This is not yet actually set, and wouldn't handle constraint derivations anyhow:
|
279
|
+
role.variable_as_projection
|
277
280
|
|
278
281
|
populate_reference role
|
279
282
|
end
|
data/lib/activefacts/version.rb
CHANGED
@@ -88,6 +88,18 @@ module ActiveFacts
|
|
88
88
|
preferred_reading.expand(frequency_constraints, define_role_names)
|
89
89
|
end
|
90
90
|
|
91
|
+
# Does any role of this fact type participate in a preferred identifier?
|
92
|
+
def is_existential
|
93
|
+
return false if all_role.size > 2
|
94
|
+
all_role.detect do |role|
|
95
|
+
role.all_role_ref.detect do |rr|
|
96
|
+
rr.role_sequence.all_presence_constraint.detect do |pc|
|
97
|
+
pc.is_preferred_identifier
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
91
103
|
def internal_presence_constraints
|
92
104
|
all_role.map do |r|
|
93
105
|
r.all_role_ref.map do |rr|
|
@@ -100,7 +112,7 @@ module ActiveFacts
|
|
100
112
|
|
101
113
|
def implicit_boolean_type vocabulary
|
102
114
|
@constellation.ImplicitBooleanValueType[[vocabulary.identifying_role_values, "_ImplicitBooleanValueType"]] ||
|
103
|
-
@constellation.ImplicitBooleanValueType(vocabulary.identifying_role_values, "_ImplicitBooleanValueType", :
|
115
|
+
@constellation.ImplicitBooleanValueType(vocabulary.identifying_role_values, "_ImplicitBooleanValueType", :concept => :new)
|
104
116
|
end
|
105
117
|
|
106
118
|
# This entity type has just objectified a fact type. Create the necessary ImplicitFactTypes with phantom roles
|
@@ -111,7 +123,7 @@ module ActiveFacts
|
|
111
123
|
# We only do it when the unary fact type is not objectified
|
112
124
|
link_fact_type = @constellation.LinkFactType(:new, :implying_role => role)
|
113
125
|
entity_type = @entity_type || implicit_boolean_type(role.object_type.vocabulary)
|
114
|
-
phantom_role = @constellation.Role(link_fact_type, 0, :object_type => entity_type, :
|
126
|
+
phantom_role = @constellation.Role(link_fact_type, 0, :object_type => entity_type, :concept => :new)
|
115
127
|
end
|
116
128
|
|
117
129
|
def reading_preferably_starting_with_role role, negated = false
|
@@ -125,6 +137,16 @@ module ActiveFacts
|
|
125
137
|
def all_role_in_order
|
126
138
|
all_role.sort_by{|r| r.ordinal}
|
127
139
|
end
|
140
|
+
|
141
|
+
def compatible_readings types_array
|
142
|
+
all_reading.select do |reading|
|
143
|
+
ok = true
|
144
|
+
reading.role_sequence.all_role_ref_in_order.each_with_index do |rr, i|
|
145
|
+
ok = false unless types_array[i].include?(rr.role.object_type)
|
146
|
+
end
|
147
|
+
ok
|
148
|
+
end
|
149
|
+
end
|
128
150
|
end
|
129
151
|
|
130
152
|
class Role
|
@@ -183,6 +205,7 @@ module ActiveFacts
|
|
183
205
|
end
|
184
206
|
|
185
207
|
def role_name(separator = "-")
|
208
|
+
return 'UNKNOWN' unless role
|
186
209
|
name_array =
|
187
210
|
if role.fact_type.all_role.size == 1
|
188
211
|
if role.fact_type.is_a?(LinkFactType)
|
@@ -380,12 +403,15 @@ module ActiveFacts
|
|
380
403
|
#pi = supertype.preferred_identifier
|
381
404
|
#return nil
|
382
405
|
elsif fact_type
|
406
|
+
possible_pi = nil
|
383
407
|
fact_type.all_role.each{|role|
|
384
408
|
role.all_role_ref.each{|role_ref|
|
385
409
|
# Discount role sequences that contain roles not in this fact type:
|
386
410
|
next if role_ref.role_sequence.all_role_ref.detect{|rr| rr.role.fact_type != fact_type }
|
387
411
|
role_ref.role_sequence.all_presence_constraint.each{|pc|
|
388
|
-
|
412
|
+
next unless pc.max_frequency == 1
|
413
|
+
possible_pi = pc
|
414
|
+
next unless pc.is_preferred_identifier
|
389
415
|
pi = pc
|
390
416
|
break
|
391
417
|
}
|
@@ -393,6 +419,10 @@ module ActiveFacts
|
|
393
419
|
}
|
394
420
|
break if pi
|
395
421
|
}
|
422
|
+
if !pi && possible_pi
|
423
|
+
debug :pi, "Using existing PC as PI for #{name}"
|
424
|
+
pi = possible_pi
|
425
|
+
end
|
396
426
|
else
|
397
427
|
debug :pi, "No PI found for #{name}"
|
398
428
|
end
|
@@ -450,7 +480,7 @@ module ActiveFacts
|
|
450
480
|
fact_type.all_role.map do |role|
|
451
481
|
next if role.link_fact_type # Already exists
|
452
482
|
link_fact_type = @constellation.LinkFactType(:new, :implying_role => role)
|
453
|
-
phantom_role = @constellation.Role(link_fact_type, 0, :object_type => self, :
|
483
|
+
phantom_role = @constellation.Role(link_fact_type, 0, :object_type => self, :concept => :new)
|
454
484
|
# We could create a copy of the visible external role here, but there's no need yet...
|
455
485
|
# Nor is there a need for a presence constraint, readings, etc.
|
456
486
|
link_fact_type
|
@@ -482,26 +512,35 @@ module ActiveFacts
|
|
482
512
|
|
483
513
|
expanded.gsub!(/\{#{i}\}/) do
|
484
514
|
role_ref = role_refs[i]
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
515
|
+
if role_ref.role
|
516
|
+
player = role_ref.role.object_type
|
517
|
+
role_name = role.role_name
|
518
|
+
role_name = nil if role_name == ""
|
519
|
+
if role_name && define_role_names == false
|
520
|
+
l_adj = t_adj = nil # When using role names, don't add adjectives
|
521
|
+
end
|
522
|
+
|
523
|
+
freq_con = frequency_constraints[i]
|
524
|
+
freq_con = freq_con.frequency if freq_con && freq_con.is_a?(ActiveFacts::Metamodel::PresenceConstraint)
|
525
|
+
if freq_con.is_a?(Array)
|
526
|
+
freq_con, player_name = *freq_con
|
527
|
+
else
|
528
|
+
player_name = player.name
|
529
|
+
end
|
530
|
+
else
|
531
|
+
# We have an unknown role. The reading cannot be correctly expanded
|
532
|
+
player_name = "UNKNOWN"
|
533
|
+
role_name = nil
|
534
|
+
freq_con = nil
|
535
|
+
end
|
536
|
+
|
498
537
|
literal = literals[i]
|
499
538
|
words = [
|
500
539
|
freq_con ? freq_con : nil,
|
501
540
|
l_adj,
|
502
541
|
define_role_names == false && role_name ? role_name : player_name,
|
503
542
|
t_adj,
|
504
|
-
define_role_names && role_name &&
|
543
|
+
define_role_names && role_name && player_name != role_name ? "(as #{role_name})" : nil,
|
505
544
|
# Can't have both a literal and a value constraint, but we don't enforce that here:
|
506
545
|
literal ? literal : nil
|
507
546
|
]
|
@@ -738,7 +777,7 @@ module ActiveFacts
|
|
738
777
|
class Query
|
739
778
|
def show
|
740
779
|
steps_shown = {}
|
741
|
-
debug :query, "Displaying full contents of Query #{guid}" do
|
780
|
+
debug :query, "Displaying full contents of Query #{concept.guid}" do
|
742
781
|
all_variable.sort_by{|jn| jn.ordinal}.each do |variable|
|
743
782
|
debug :query, "#{variable.describe}" do
|
744
783
|
variable.all_step.
|
@@ -820,6 +859,7 @@ module ActiveFacts
|
|
820
859
|
# This is only used for debugging, from RoleRef#describe
|
821
860
|
class ImplicitReading
|
822
861
|
attr_accessor :fact_type, :text
|
862
|
+
attr_reader :is_negative # Never true
|
823
863
|
|
824
864
|
def initialize(fact_type, text)
|
825
865
|
@fact_type = fact_type
|