activefacts-orm 1.8.1 → 1.9.1
Sign up to get free protection for your applications and to get access to all the features.
- 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.
|