activefacts-orm 1.8.1 → 1.9.1
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.
- checksums.yaml +4 -4
- data/Gemfile +6 -5
- data/activefacts-orm.gemspec +1 -1
- data/lib/activefacts/input/orm.rb +246 -242
- data/lib/activefacts/orm/version.rb +1 -1
- metadata +3 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d11a6d2ace0ba599a5dc70be538eaa0f45156cc4
|
4
|
+
data.tar.gz: 0e780821ecbdfa6117fca7f8c9eb4846b6676334
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 25d1a64a911785cb3dbf79dec12a3ea3fe4969eb3db1c8f77557464bbe853eba0f5579d8283df7ec874cf08817c3a60d9a3839d7206ec1111a70eb5a365f0554
|
7
|
+
data.tar.gz: 14781211da5268161c4f73d826a89a14f8a62b6e14a50acf2bfbf37f9e01434f5db3f8638a58d7595e0493d4cadbfe4f404c39b9d79517c2dbf4f9f08301be54
|
data/Gemfile
CHANGED
@@ -2,9 +2,10 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
gemspec
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
this_file = File.absolute_path(__FILE__)
|
6
|
+
if this_file =~ %r{\A#{ENV['HOME']}}i
|
7
|
+
dir = File.dirname(File.dirname(this_file))
|
8
|
+
$stderr.puts "Using work area gems in #{dir} from activefacts-orm"
|
9
|
+
gem 'activefacts-api', path: dir+'/api'
|
10
|
+
gem 'activefacts-metamodel', path: dir+'/metamodel'
|
10
11
|
end
|
data/activefacts-orm.gemspec
CHANGED
@@ -19,7 +19,7 @@ Install the Natural ORM Architect from http://ormfoundation.org to produce input
|
|
19
19
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
20
20
|
spec.require_paths = ["lib"]
|
21
21
|
|
22
|
-
spec.add_development_dependency "bundler", ">= 1.10"
|
22
|
+
spec.add_development_dependency "bundler", ">= 1.10"
|
23
23
|
spec.add_development_dependency "rake", "~> 10.0"
|
24
24
|
spec.add_development_dependency "rspec", "~> 3.3"
|
25
25
|
|
@@ -72,13 +72,13 @@ module ActiveFacts
|
|
72
72
|
|
73
73
|
private
|
74
74
|
def self.readfile(filename, *options)
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
75
|
+
if File.basename(filename, '.orm') == "-"
|
76
|
+
self.read(STDIN, "<standard input>", options)
|
77
|
+
else
|
78
|
+
File.open(filename) {|file|
|
79
|
+
self.read(file, filename, *options)
|
80
|
+
}
|
81
|
+
end
|
82
82
|
end
|
83
83
|
|
84
84
|
def self.read(file, filename = "stdin", *options)
|
@@ -149,7 +149,7 @@ module ActiveFacts
|
|
149
149
|
end
|
150
150
|
|
151
151
|
def id_of(x)
|
152
|
-
|
152
|
+
x['id'][1..-1]
|
153
153
|
end
|
154
154
|
|
155
155
|
def read_entity_types
|
@@ -160,17 +160,17 @@ module ActiveFacts
|
|
160
160
|
id = x['id']
|
161
161
|
name = (x['Name'] || "").gsub(/\s+/,' ').gsub(/-/,'_').strip
|
162
162
|
name = nil if name.size == 0
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
163
|
+
entity_type =
|
164
|
+
@by_id[id] =
|
165
|
+
trace :orm, "Asserting new EntityType #{name.inspect}" do
|
166
|
+
@vocabulary.valid_entity_type_name(name) ||
|
167
|
+
@constellation.EntityType(@vocabulary, name, :concept => id_of(x))
|
168
|
+
end
|
169
|
+
entity_types << entity_type
|
170
|
+
independent = x['IsIndependent']
|
171
|
+
entity_type.is_independent = true if independent && independent == 'true'
|
172
|
+
personal = x['IsPersonal']
|
173
|
+
entity_type.pronoun = 'personal' if personal && personal == 'true'
|
174
174
|
# x_pref = x.xpath("orm:PreferredIdentifier")[0]
|
175
175
|
# if x_pref
|
176
176
|
# pi_id = x_pref['ref']
|
@@ -209,21 +209,21 @@ module ActiveFacts
|
|
209
209
|
type_name.sub!(/^orm:/,'')
|
210
210
|
|
211
211
|
type_name.sub!(/DataType\Z/,'')
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
212
|
+
if t = DataTypeMapping[type_name]
|
213
|
+
existing = @constellation.ObjectType[[@vocabulary.identifying_role_values, t]]
|
214
|
+
if !existing || existing.is_a?(ActiveFacts::Metamodel::ValueType)
|
215
|
+
# There's no type conflict, so use the mapped name.
|
216
|
+
type_name = t
|
217
|
+
end
|
218
|
+
end
|
219
|
+
trace :orm, "Using #{type_name.inspect} as supertype for new #{name}"
|
220
220
|
if !length and type_name =~ /\(([0-9]+)\)/
|
221
221
|
length = $1.to_i
|
222
222
|
end
|
223
223
|
type_name = type_name.sub(/\(([0-9]*)\)/,'')
|
224
224
|
|
225
225
|
subtype_roles = x.xpath("orm:PlayedRoles/orm:SubtypeMetaRole")
|
226
|
-
|
226
|
+
value_super_type = nil
|
227
227
|
if !subtype_roles.empty?
|
228
228
|
subtype_role_id = subtype_roles[0]['ref']
|
229
229
|
subtype_role = @x_by_id[subtype_role_id]
|
@@ -235,30 +235,30 @@ module ActiveFacts
|
|
235
235
|
supertype_name = x_supertype['Name']
|
236
236
|
raise "Supertype of #{name} is post-defined but recursiving processing failed" unless supertype
|
237
237
|
raise "Supertype #{supertype_name} of #{name} is not a value type" unless supertype.kind_of? ActiveFacts::Metamodel::ValueType
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
238
|
+
trace :orm, "Asserting new ValueType #{supertype_name.inspect} for supertype" do
|
239
|
+
value_super_type =
|
240
|
+
@vocabulary.valid_value_type_name(supertype_name) ||
|
241
|
+
@constellation.ValueType(@vocabulary, supertype_name, :concept => id_of(x_supertype))
|
242
|
+
end
|
243
243
|
else
|
244
244
|
# REVISIT: Need to handle standard types better here:
|
245
245
|
value_super_type =
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
246
|
+
if type_name != name
|
247
|
+
trace :orm, "Asserting new ValueType #{type_name.inspect} for supertype" do
|
248
|
+
@vocabulary.valid_value_type_name(type_name) ||
|
249
|
+
@constellation.ValueType(@vocabulary.identifying_role_values, type_name, :concept => :new)
|
250
|
+
end
|
251
|
+
else
|
252
|
+
nil
|
253
|
+
end
|
254
254
|
end
|
255
255
|
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
256
|
+
vt =
|
257
|
+
trace :orm, "Asserting new ValueType #{name.inspect}" do
|
258
|
+
@by_id[id] =
|
259
|
+
@vocabulary.valid_value_type_name(name) ||
|
260
|
+
@constellation.ValueType(@vocabulary.identifying_role_values, name, :concept => id_of(x))
|
261
|
+
end
|
262
262
|
vt.supertype = value_super_type
|
263
263
|
vt.length = length if length
|
264
264
|
vt.scale = scale if scale && scale != 0
|
@@ -281,11 +281,11 @@ module ActiveFacts
|
|
281
281
|
end
|
282
282
|
|
283
283
|
def assert_value(val, string)
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
284
|
+
if val
|
285
|
+
@constellation.Value(val.to_s, string, nil)
|
286
|
+
else
|
287
|
+
nil
|
288
|
+
end
|
289
289
|
end
|
290
290
|
|
291
291
|
def value_range(x_range)
|
@@ -294,9 +294,9 @@ module ActiveFacts
|
|
294
294
|
|
295
295
|
strings = is_literal_string(min) || is_literal_string(max)
|
296
296
|
# ValueRange takes a minimum and/or a maximum Bound, each takes value and whether inclusive
|
297
|
-
|
298
|
-
|
299
|
-
|
297
|
+
@constellation.ValueRange(
|
298
|
+
min.length > 0 ? @constellation.Bound(assert_value(min, strings), true) : nil,
|
299
|
+
max.length > 0 ? @constellation.Bound(assert_value(max, strings), true) : nil)
|
300
300
|
end
|
301
301
|
|
302
302
|
def read_fact_types
|
@@ -411,8 +411,8 @@ module ActiveFacts
|
|
411
411
|
trace :orm, "NestedType #{name} is #{id}, nests #{fact_type.concept.guid}"
|
412
412
|
@nested_types <<
|
413
413
|
@by_id[id] =
|
414
|
-
|
415
|
-
|
414
|
+
nested_type = @vocabulary.valid_entity_type_name(name) ||
|
415
|
+
@constellation.EntityType(@vocabulary, name, :concept => id_of(x))
|
416
416
|
independent = x['IsIndependent']
|
417
417
|
nested_type.is_independent = true if independent && independent == 'true' && !is_implied
|
418
418
|
nested_type.concept.implication_rule = 'objectification' if is_implied
|
@@ -474,9 +474,9 @@ module ActiveFacts
|
|
474
474
|
@by_id.delete(ref) # and de-index it from our list
|
475
475
|
next
|
476
476
|
end
|
477
|
-
|
478
|
-
|
479
|
-
|
477
|
+
if !object_type
|
478
|
+
throw "RolePlayer for '#{name}' #{ref} in fact type #{x.parent.parent['_Name']} was not found"
|
479
|
+
end
|
480
480
|
|
481
481
|
trace :orm, "#{@vocabulary.name}, RoleName=#{x['Name'].inspect} played by object_type=#{object_type.name}"
|
482
482
|
throw "Role is played by #{object_type.class} not ObjectType" if !(@constellation.vocabulary.object_type(:ObjectType) === object_type)
|
@@ -506,7 +506,7 @@ module ActiveFacts
|
|
506
506
|
|
507
507
|
# Deal with Readings:
|
508
508
|
trace :orm, "Reading fact readings" do
|
509
|
-
|
509
|
+
x_reading_orders = x.xpath('orm:ReadingOrders/*')
|
510
510
|
x_reading_orders.each{|x|
|
511
511
|
x_role_sequence = x.xpath('orm:RoleSequence/*')
|
512
512
|
x_readings = x.xpath('orm:Readings/orm:Reading/orm:Data')
|
@@ -551,13 +551,15 @@ module ActiveFacts
|
|
551
551
|
text.gsub!(role_with_adjectives_re) {
|
552
552
|
# REVISIT: Don't want to strip all spaces here any more:
|
553
553
|
#puts "text=#{text.inspect}, la=#{$1.inspect}, ta=#{$2.inspect}" if $1 || $2
|
554
|
-
la = ($1||'')
|
555
|
-
ta = ($2||'')
|
554
|
+
la = ($1||'')
|
555
|
+
ta = ($2||'')
|
556
|
+
la.gsub!(/\s+/,' ') # Strip duplicate spaces
|
557
|
+
ta.gsub!(/\s+/,' ')
|
556
558
|
# When we have "aaa-bbb" we want "aaa bbb"
|
557
559
|
# When we have "aaa- bbb" we want "aaa bbb"
|
558
560
|
# When we have "aaa-- bbb" we want "aaa-bbb"
|
559
|
-
la = la.sub(
|
560
|
-
ta = ta.sub(/
|
561
|
+
la = la.sub(/-- +/,'-').sub(/-( |$)/,' ').strip
|
562
|
+
ta = ta.sub(/ *--/,'-').sub(/(^| )-/,' ').strip
|
561
563
|
#puts "Setting leading adj #{la.inspect} from #{text.inspect} for #{role_ref.role.object_type.name}" if la != ""
|
562
564
|
# REVISIT: Dunno what's up here, but removing the "if" test makes this chuck exceptions:
|
563
565
|
role_ref.leading_adjective = la if la != ""
|
@@ -576,7 +578,7 @@ module ActiveFacts
|
|
576
578
|
case w
|
577
579
|
when /[A-Za-z]/
|
578
580
|
if RESERVED_WORDS.include?(w)
|
579
|
-
$stderr.puts "Masking reserved word '#{w}' in reading '#{text}'"
|
581
|
+
$stderr.puts "Masking reserved word '#{w}' in reading '#{text}' with players #{all_role_refs.map(&:role).map(&:name).inspect}"
|
580
582
|
next "_#{w}"
|
581
583
|
elsif @constellation.ObjectType[[[@vocabulary.name], w]]
|
582
584
|
$stderr.puts "Masking object type name '#{w}' in reading '#{text}'"
|
@@ -760,13 +762,13 @@ module ActiveFacts
|
|
760
762
|
join_over, = *ActiveFacts::Metamodel.plays_over(role_sequence.all_role_ref.map{|rr| rr.role}, :counterpart)
|
761
763
|
|
762
764
|
players = role_sequence.all_role_ref.map{|rr| rr.role.object_type.name}.uniq
|
763
|
-
|
764
|
-
|
765
|
-
|
766
|
-
|
767
|
-
|
768
|
-
|
769
|
-
|
765
|
+
unless join_over
|
766
|
+
if x.xpath("orm:RoleSequence/orm:JoinRule").size > 0
|
767
|
+
$stderr.puts "Ignoring Join #{name} because its query is not understood"
|
768
|
+
next
|
769
|
+
end
|
770
|
+
raise "Uniqueness join constraint #{name} has incompatible players #{players.inspect}"
|
771
|
+
end
|
770
772
|
subtyping = players.size > 1 ? 'subtyping ' : ''
|
771
773
|
# REVISIT: Create the Query, the Variable for join_over, and steps from each role_ref to join_over
|
772
774
|
trace :query, "#{subtyping}join uniqueness constraint over #{join_over.name} in #{fact_types.map(&:default_reading)*', '}"
|
@@ -836,7 +838,7 @@ module ActiveFacts
|
|
836
838
|
@constellation.Variable(query, query.all_variable.size, :object_type => ti.subtype)
|
837
839
|
supertype_node = query.all_variable.detect{|jn| jn.object_type == ti.supertype } ||
|
838
840
|
@constellation.Variable(query, query.all_variable.size, :object_type => ti.supertype)
|
839
|
-
step = @constellation.Step(:
|
841
|
+
step = @constellation.Step(:query => query, :ordinal => query.all_step.size, :fact_type => ti)
|
840
842
|
rs = @constellation.RoleSequence(:new)
|
841
843
|
@constellation.RoleRef(rs, 0, :role => ti.subtype_role)
|
842
844
|
sub_play = @constellation.Play(:step => step, :variable => subtype_node, :role => ti.subtype_role)
|
@@ -865,149 +867,150 @@ module ActiveFacts
|
|
865
867
|
end
|
866
868
|
|
867
869
|
# If there's a query, build it and return a new RoleSequence containing the projected roles:
|
868
|
-
def query_over_role_sequence(role_sequence, join_over, joined_roles, end_points)
|
869
|
-
|
870
|
-
|
871
|
-
|
872
|
-
|
873
|
-
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
952
|
-
|
953
|
-
|
954
|
-
|
955
|
-
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
964
|
-
|
965
|
-
|
966
|
-
|
870
|
+
def query_over_role_sequence(constraint_desc, role_sequence, join_over, joined_roles, end_points)
|
871
|
+
# Skip if there's no query here (sequence join nor end-point subset join)
|
872
|
+
role_refs = role_sequence.all_role_ref_in_order
|
873
|
+
if !join_over and !role_refs.detect{|rr| rr.role.object_type != end_points[rr.ordinal]}
|
874
|
+
# No sequence join nor end_point join here
|
875
|
+
return role_sequence
|
876
|
+
end
|
877
|
+
|
878
|
+
# A RoleSequence for the actual query end-points
|
879
|
+
replacement_rs = @constellation.RoleSequence(:new)
|
880
|
+
|
881
|
+
query = @constellation.Query(:new)
|
882
|
+
variable = nil
|
883
|
+
query_role = nil
|
884
|
+
role_refs.zip(joined_roles||[]).each_with_index do |(role_ref, joined_role), i|
|
885
|
+
|
886
|
+
# Each role_ref is to an object joined via joined_role to variable (or which will be the variable)
|
887
|
+
|
888
|
+
# Create a variable for the actual end-point (supertype of the constrained roles)
|
889
|
+
end_point = end_points[i]
|
890
|
+
unless end_point
|
891
|
+
raise "In #{constraint_desc}, there is a faulty or non-translated query"
|
892
|
+
end
|
893
|
+
trace :query, "Variable #{query.all_variable.size} is for #{end_point.name}"
|
894
|
+
end_node = @constellation.Variable(query, query.all_variable.size, :object_type => end_point)
|
895
|
+
|
896
|
+
# We're going to rewrite the constraint to constrain the supertype roles, but assume they're the same:
|
897
|
+
role_node = end_node
|
898
|
+
end_role = role_ref.role
|
899
|
+
|
900
|
+
# Create subtyping steps at the end-point, if needed:
|
901
|
+
projecting_play = nil
|
902
|
+
constrained_play = nil
|
903
|
+
if (subtype = role_ref.role.object_type) != end_point
|
904
|
+
trace :query, "Making subtyping steps from #{subtype.name} to #{end_point.name}" do
|
905
|
+
# There may be more than one supertyping level. Make the steps:
|
906
|
+
subtyping_steps = subtype_steps(query, subtype, end_point)
|
907
|
+
step = subtyping_steps[0]
|
908
|
+
#constrained_play = subtyping_steps[-1].all_play.detect{|p| p.role.object_type == end_point}
|
909
|
+
subtyping_steps.detect{|s| constrained_play = s.all_play.detect{|p| p.role.object_type == end_point}}
|
910
|
+
|
911
|
+
# Replace the constrained role and node with the supertype ones:
|
912
|
+
end_node = query.all_variable.detect{|jn| jn.object_type == end_point }
|
913
|
+
#projecting_play = step.all_play.detect{|p| p.role.object_type == subtype}
|
914
|
+
subtyping_steps.detect{|s| projecting_play = s.all_play.detect{|p| p.role.object_type == subtype}}
|
915
|
+
end_role = step.fact_type.all_role.detect{|r| r.object_type == end_point }
|
916
|
+
role_node = query.all_variable.detect{|jn| jn.object_type == role_ref.role.object_type }
|
917
|
+
end
|
918
|
+
end
|
919
|
+
|
920
|
+
if end_role.object_type != end_node.object_type
|
921
|
+
raise "Internal error in #{constraint_desc}: making illegal reference to variable, end role mismatch"
|
922
|
+
end
|
923
|
+
|
924
|
+
if join_over
|
925
|
+
if !variable # Create the Variable when processing the first role
|
926
|
+
trace :query, "Variable #{query.all_variable.size} is over #{join_over.name}"
|
927
|
+
variable = @constellation.Variable(query, query.all_variable.size, :object_type => join_over)
|
928
|
+
end
|
929
|
+
trace :query, "Making step from #{end_point.name} to #{join_over.name}" do
|
930
|
+
rs = @constellation.RoleSequence(:new)
|
931
|
+
# Detect the fact type over which we're stepping (may involve objectification)
|
932
|
+
raise "Internal error in #{constraint_desc}: making illegal reference to variable, object type mismatch" if role_ref.role.object_type != role_node.object_type
|
933
|
+
step = @constellation.Step(:query => query, :ordinal => query.all_step.size, :fact_type => joined_role.fact_type)
|
934
|
+
@constellation.RoleRef(rs, 0, :role => role_ref.role)
|
935
|
+
role_play = @constellation.Play(:step => step, :variable => role_node, :role => role_ref.role, :is_input => true)
|
936
|
+
# Make the projected RoleRef:
|
937
|
+
rr = @constellation.RoleRef(replacement_rs, replacement_rs.all_role_ref.size, :role => role_ref.role, :play => role_play)
|
938
|
+
raise "Internal error in #{constraint_desc}: making illegal reference to variable, joined_role mismatch" if joined_role.object_type != variable.object_type
|
939
|
+
@constellation.RoleRef(rs, 1, :role => joined_role)
|
940
|
+
join_play = @constellation.Play(:step => step, :variable => variable, :role => joined_role)
|
941
|
+
trace :query, "New step #{step.describe}"
|
942
|
+
end
|
943
|
+
else
|
944
|
+
trace :query, "Need step for non-join_over role #{end_point.name} #{role_ref.describe} in #{role_ref.role.fact_type.default_reading}"
|
945
|
+
if (roles = role_ref.role.fact_type.all_role.to_a).size > 1
|
946
|
+
# Here we have an end join (step already created) but no sequence join
|
947
|
+
if variable
|
948
|
+
raise "Internal error in #{constraint_desc}: making illegal step" if role_ref.role.object_type != role_node.object_type
|
949
|
+
step = @constellation.Step(:query => query, :ordinal => query.all_step.size, :fact_type => role_ref.role.fact_type)
|
950
|
+
join_play = @constellation.Play(:step => step, :variable => variable, :role => query_role, :is_input => true)
|
951
|
+
role_play = @constellation.Play(:step => step, :variable => role_node, :role => role_ref.role)
|
952
|
+
# Make the projected RoleRef:
|
953
|
+
rr = @constellation.RoleRef(replacement_rs, replacement_rs.all_role_ref.size, :role => role_ref.role, :play => role_play)
|
954
|
+
roles -= [query_role, role_ref.role]
|
955
|
+
roles.each do |incidental_role|
|
956
|
+
jn = @constellation.Variable(query, query.all_variable.size, :object_type => incidental_role.object_type)
|
957
|
+
play = @constellation.Play(:step => step, :variable => jn, :role => incidental_role)
|
958
|
+
end
|
959
|
+
else
|
960
|
+
|
961
|
+
if role_sequence.all_role_ref.size > 1
|
962
|
+
variable = role_node
|
963
|
+
query_role = role_ref.role
|
964
|
+
|
965
|
+
# Make the projected RoleRef:
|
966
|
+
return role_sequence unless constrained_play # REVISIT: This is a fail; survive it.
|
967
|
+
rr = @constellation.RoleRef(replacement_rs, replacement_rs.all_role_ref.size, :role => constrained_play.role, :play => constrained_play)
|
968
|
+
else
|
969
|
+
# We enter this fact type (requiring that a role be played) but don't exit it.
|
967
970
|
# I think this can only happen where we have subtyping steps, above.
|
968
971
|
|
969
|
-
|
970
|
-
|
971
|
-
|
972
|
-
|
973
|
-
|
974
|
-
|
975
|
-
|
976
|
-
|
977
|
-
|
978
|
-
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
#
|
984
|
-
#
|
985
|
-
#
|
986
|
-
#
|
987
|
-
#
|
988
|
-
#
|
989
|
-
#
|
990
|
-
#
|
991
|
-
#
|
992
|
-
#
|
993
|
-
|
994
|
-
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
|
1004
|
-
|
1005
|
-
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
972
|
+
# There's no query in this role sequence, so we'd drop off the bottom without doing the right things. Why?
|
973
|
+
# Without this case, Supervision.orm omits "that runs Company" from the exclusion constraint, and I'm not sure why.
|
974
|
+
# I think the "then" code causes it to drop out the bottom without making the step (which is otherwise made in every case, see CompanyDirectorEmployee for example)
|
975
|
+
step = @constellation.Step(:query => query, :ordinal => query.all_step.size, :fact_type => role_ref.role.fact_type)
|
976
|
+
|
977
|
+
# p constrained_play.role.object_type.name
|
978
|
+
# p projecting_play.role.object_type.name
|
979
|
+
# debugger
|
980
|
+
|
981
|
+
role_play = @constellation.Play(:step => step, :variable => role_node, :role => role_ref.role, :is_input => true)
|
982
|
+
|
983
|
+
# Make the projected RoleRef:
|
984
|
+
rr = @constellation.RoleRef(replacement_rs, replacement_rs.all_role_ref.size, :role => constrained_play.role, :play => constrained_play)
|
985
|
+
|
986
|
+
# role_ref.role.fact_type.all_role.each do |role|
|
987
|
+
# next if role == role_play.role
|
988
|
+
# next if role_sequence.all_role_ref.detect{|rr| rr.role == role}
|
989
|
+
# jn = @constellation.Variable(query, query.all_variable.size, :object_type => role.object_type)
|
990
|
+
# play = @constellation.Play(:step => step, :variable => jn, :role => role)
|
991
|
+
# if role == role_ref.role
|
992
|
+
# # Make the projected RoleRef:
|
993
|
+
# rr = @constellation.RoleRef(replacement_rs, replacement_rs.all_role_ref.size, :role => role, :play => play)
|
994
|
+
# end
|
995
|
+
# end
|
996
|
+
|
997
|
+
end
|
998
|
+
end
|
999
|
+
else
|
1000
|
+
# Unary fact type, make a Step from and to the constrained_play
|
1001
|
+
step = @constellation.Step(:query => query, :ordinal => query.all_step.size, :fact_type => role_ref.role.fact_type)
|
1002
|
+
play = @constellation.Play(:step => step, :variable => constrained_play.variable, :role => role_ref.role, :is_input => true)
|
1003
|
+
# Make the projected RoleRef:
|
1004
|
+
rr = @constellation.RoleRef(replacement_rs, replacement_rs.all_role_ref.size, :role => role_ref.role, :play => play)
|
1005
|
+
end
|
1006
|
+
end
|
1007
|
+
end
|
1008
|
+
raise "hell" if replacement_rs.all_role_ref.size != role_sequence.all_role_ref.size
|
1009
|
+
|
1010
|
+
# Thoroughly check that this is a valid query
|
1011
|
+
query.validate
|
1012
|
+
trace :query, "Query has projected nodes #{replacement_rs.describe}"
|
1013
|
+
replacement_rs
|
1011
1014
|
end
|
1012
1015
|
|
1013
1016
|
# Equality and subset join constraints involve two or more role sequences,
|
@@ -1019,6 +1022,7 @@ module ActiveFacts
|
|
1019
1022
|
#
|
1020
1023
|
def make_queries(constraint_type, name, role_sequences)
|
1021
1024
|
begin
|
1025
|
+
constraint_desc = "#{constraint_type} #{name}"
|
1022
1026
|
# Get the object types constrained for each position in the role sequences.
|
1023
1027
|
# Supertyping steps may be needed to reach them.
|
1024
1028
|
end_points = [] # An array of the common supertype for matching role_refs across the sequences
|
@@ -1027,10 +1031,10 @@ module ActiveFacts
|
|
1027
1031
|
role_refs = role_sequences.map{|rs| rs.all_role_ref.detect{|rr| rr.ordinal == i}}
|
1028
1032
|
if (fact_types = role_refs.map{|rr| rr.role.fact_type}).uniq.size == 1
|
1029
1033
|
# $stderr.puts(role_sequences.map{|rs| rs.all_role_ref.map{|rr| rr.role.fact_type.describe(rr.role)}}.inspect)
|
1030
|
-
raise "In #{
|
1034
|
+
raise "In #{constraint_desc} role sequence #{i}, there is a faulty join involving just 1 fact type: '#{fact_types[0].default_reading}'"
|
1031
1035
|
end
|
1032
1036
|
if (players = role_refs.map{|rr| rr.role.object_type}).uniq.size == 1
|
1033
|
-
|
1037
|
+
# All roles in this set are played by the same object type
|
1034
1038
|
end_point = players[0]
|
1035
1039
|
end_step_needed[i] = false
|
1036
1040
|
else
|
@@ -1041,7 +1045,7 @@ module ActiveFacts
|
|
1041
1045
|
end
|
1042
1046
|
end_point = common_supertypes[0]
|
1043
1047
|
|
1044
|
-
raise "constrained roles of #{
|
1048
|
+
raise "constrained roles of #{constraint_desc} are incompatible (#{players.map(&:name)*', '})" if common_supertypes.size == 0
|
1045
1049
|
end_step_needed[i] = true
|
1046
1050
|
end
|
1047
1051
|
end_points[i] = end_point
|
@@ -1064,10 +1068,10 @@ module ActiveFacts
|
|
1064
1068
|
return true
|
1065
1069
|
end
|
1066
1070
|
|
1067
|
-
trace :query, "#{
|
1071
|
+
trace :query, "#{constraint_desc} over #{role_sequences.map{|rs|rs.describe}*', '}"
|
1068
1072
|
|
1069
1073
|
query = nil
|
1070
|
-
trace :query, "#{
|
1074
|
+
trace :query, "#{constraint_desc} constrains #{
|
1071
1075
|
end_points.zip(end_step_needed).map{|(p,j)| (p ? p.name : 'NULL')+(j ? ' & subtypes':'')}*', '
|
1072
1076
|
}#{
|
1073
1077
|
if role_sequences[0].all_role_ref.size > 1
|
@@ -1083,12 +1087,12 @@ module ActiveFacts
|
|
1083
1087
|
|
1084
1088
|
# There may be one query per role sequence:
|
1085
1089
|
role_sequences.zip(sequence_join_over||[], sequence_joined_roles||[]).map do |role_sequence, join_over, joined_roles|
|
1086
|
-
|
1087
|
-
|
1088
|
-
|
1089
|
-
|
1090
|
-
|
1091
|
-
|
1090
|
+
position = role_sequences.index(role_sequence)
|
1091
|
+
replacement_rs = query_over_role_sequence(constraint_desc, role_sequence, join_over, joined_roles, end_points)
|
1092
|
+
if role_sequence != replacement_rs
|
1093
|
+
role_sequences[position] = replacement_rs
|
1094
|
+
end
|
1095
|
+
end
|
1092
1096
|
|
1093
1097
|
return true
|
1094
1098
|
end
|
@@ -1124,15 +1128,15 @@ module ActiveFacts
|
|
1124
1128
|
@mandatory_constraints_by_rs.delete(mc_rs)
|
1125
1129
|
end
|
1126
1130
|
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
+
if role_sequences.compact.size != role_sequences.size # Role sequence missing; includes a derived fact type role
|
1132
|
+
trace :orm, "skipped exclusion constraint #{id}, missing role sequence"
|
1133
|
+
next
|
1134
|
+
end
|
1131
1135
|
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1136
|
+
unless make_queries('exclusion', name+(x_mandatory ? '/'+x_mandatory['Name'] : ''), role_sequences)
|
1137
|
+
trace :orm, "skipped exclusion constraint #{id}, can't make_queries"
|
1138
|
+
next
|
1139
|
+
end
|
1136
1140
|
|
1137
1141
|
ec = @constellation.SetExclusionConstraint(id_of(x))
|
1138
1142
|
ec.vocabulary = @vocabulary
|
@@ -1326,7 +1330,7 @@ module ActiveFacts
|
|
1326
1330
|
end
|
1327
1331
|
|
1328
1332
|
# The EntityType instances have implicit facts for the PI facts.
|
1329
|
-
|
1333
|
+
# These are in the ORM file, but instead of using those,
|
1330
1334
|
# We create implicit PI facts after all the instances.
|
1331
1335
|
entity_count = 0
|
1332
1336
|
pi_fact_count = 0
|
@@ -1377,7 +1381,7 @@ module ActiveFacts
|
|
1377
1381
|
# Use the "ref" attribute of FactTypeRoleInstance:
|
1378
1382
|
x_fact_roles = @x_model.xpath("orm:Facts/orm:Fact/orm:Instances/orm:FactTypeInstance/orm:RoleInstances/orm:FactTypeRoleInstance")
|
1379
1383
|
|
1380
|
-
|
1384
|
+
# REVISIT: This presumably duplicates the identifying fact instances for the above entities. Hmmm.
|
1381
1385
|
last_id = nil
|
1382
1386
|
fact = nil
|
1383
1387
|
fact_roles = []
|
@@ -1449,7 +1453,7 @@ module ActiveFacts
|
|
1449
1453
|
location = convert_location(bounds, Gravity::C)
|
1450
1454
|
# $stderr.puts "#{subject.name}: bounds=#{bounds} -> location = (#{location.x}, #{location.y})"
|
1451
1455
|
shape = @constellation.ObjectTypeShape(
|
1452
|
-
:guid => id_of(x_shape), :orm_diagram => diagram, :
|
1456
|
+
:guid => id_of(x_shape), :orm_diagram => diagram, :is_expanded => is_expanded,
|
1453
1457
|
:object_type => subject,
|
1454
1458
|
:location => location
|
1455
1459
|
)
|
@@ -1522,12 +1526,12 @@ module ActiveFacts
|
|
1522
1526
|
when 'ObjectifiedFactTypeNameShape'
|
1523
1527
|
@constellation.ObjectifiedFactTypeNameShape(:guid => id_of(xr_shape), :fact_type_shape => shape, :orm_diagram => diagram, :location => location, :is_expanded => false)
|
1524
1528
|
when 'ReadingShape'
|
1525
|
-
|
1529
|
+
begin
|
1526
1530
|
@constellation.ReadingShape(:guid => id_of(xr_shape), :fact_type_shape => shape, :orm_diagram => diagram, :location => location, :is_expanded => false, :reading => fact_type.preferred_reading)
|
1527
|
-
|
1528
|
-
|
1529
|
-
|
1530
|
-
|
1531
|
+
rescue =>e
|
1532
|
+
debugger
|
1533
|
+
@constellation.ReadingShape(:guid => id_of(xr_shape), :fact_type_shape => shape, :orm_diagram => diagram, :location => location, :is_expanded => false, :reading => fact_type.preferred_reading)
|
1534
|
+
end
|
1531
1535
|
when 'RoleNameShape'
|
1532
1536
|
role = @by_id[xr_shape.xpath("ormDiagram:Subject")[0]['ref']]
|
1533
1537
|
role_display = role_display_for_role(shape, x_role_display, role)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activefacts-orm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.9.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Clifford Heath
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-10-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -17,9 +17,6 @@ dependencies:
|
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.10'
|
20
|
-
- - "~>"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 1.10.6
|
23
20
|
type: :development
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -27,9 +24,6 @@ dependencies:
|
|
27
24
|
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '1.10'
|
30
|
-
- - "~>"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 1.10.6
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: rake
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -137,7 +131,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
131
|
version: '0'
|
138
132
|
requirements: []
|
139
133
|
rubyforge_project:
|
140
|
-
rubygems_version: 2.
|
134
|
+
rubygems_version: 2.4.5
|
141
135
|
signing_key:
|
142
136
|
specification_version: 4
|
143
137
|
summary: ORM format importer for the ActiveFacts fact modeling suite.
|