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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a125b784f0eaec6df2554dbe8200a0b8b5e586d
4
- data.tar.gz: f14ae3e17e85ef8efa2763e12bcc2f26017c110f
3
+ metadata.gz: d11a6d2ace0ba599a5dc70be538eaa0f45156cc4
4
+ data.tar.gz: 0e780821ecbdfa6117fca7f8c9eb4846b6676334
5
5
  SHA512:
6
- metadata.gz: f0cf8d798d357eff4466547c425c166c9320a10e4a07f08ff039101aee2a3f7b5c597161d9453005ec202350b0b958ae019a642c09dc481ad77f76786f991d9d
7
- data.tar.gz: 91fa8a98cb549964a71579420c1a0d4aee49cba03292e2f468995aedd7559c750722bef22155e283eb9693923b077a8952569dd3a9c20e84dcb5fff5fa93ac42
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
- if ENV['PWD'] =~ %r{\A#{ENV['HOME']}/work}
6
- $stderr.puts "Using work area gems for #{File.basename(File.dirname(__FILE__))} from activefacts-orm"
7
- gem 'activefacts-api', path: '/Users/cjh/work/activefacts/api'
8
- gem 'activefacts-metamodel', path: '/Users/cjh/work/activefacts/metamodel'
9
- # gem 'activefacts-metamodel', git: 'git://github.com/cjheath/activefacts-metamodel.git'
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
@@ -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", "~> 1.10.6"
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
- 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
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
- x['id'][1..-1]
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
- 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'
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
- 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}"
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
- value_super_type = nil
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
- 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
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
- 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
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
- 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
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
- if val
285
- @constellation.Value(val.to_s, string, nil)
286
- else
287
- nil
288
- end
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
- @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)
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
- nested_type = @vocabulary.valid_entity_type_name(name) ||
415
- @constellation.EntityType(@vocabulary, name, :concept => id_of(x))
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
- if !object_type
478
- throw "RolePlayer for '#{name}' #{ref} in fact type #{x.parent.parent['_Name']} was not found"
479
- end
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
- x_reading_orders = x.xpath('orm:ReadingOrders/*')
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||'').gsub(/\s+/,' ') # Strip duplicate spaces
555
- ta = ($2||'').gsub(/\s+/,' ')
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(/(-)?- ?/,'\1').strip
560
- ta = ta.sub(/ ?(-)?-/,'\1').strip
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
- unless join_over
764
- if x.xpath("orm:RoleSequence/orm:JoinRule").size > 0
765
- $stderr.puts "Ignoring Join #{name} because its query is not understood"
766
- next
767
- end
768
- raise "Uniqueness join constraint #{name} has incompatible players #{players.inspect}"
769
- end
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(:guid => :new, :fact_type => ti)
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
- # Skip if there's no query here (sequence join nor end-point subset join)
870
- role_refs = role_sequence.all_role_ref_in_order
871
- if !join_over and !role_refs.detect{|rr| rr.role.object_type != end_points[rr.ordinal]}
872
- # No sequence join nor end_point join here
873
- return role_sequence
874
- end
875
-
876
- # A RoleSequence for the actual query end-points
877
- replacement_rs = @constellation.RoleSequence(:new)
878
-
879
- query = @constellation.Query(:new)
880
- variable = nil
881
- query_role = nil
882
- role_refs.zip(joined_roles||[]).each_with_index do |(role_ref, joined_role), i|
883
-
884
- # Each role_ref is to an object joined via joined_role to variable (or which will be the variable)
885
-
886
- # Create a variable for the actual end-point (supertype of the constrained roles)
887
- end_point = end_points[i]
888
- unless end_point
889
- raise "In #{constraint_type} #{name}, there is a faulty or non-translated query"
890
- end
891
- trace :query, "Variable #{query.all_variable.size} is for #{end_point.name}"
892
- end_node = @constellation.Variable(query, query.all_variable.size, :object_type => end_point)
893
-
894
- # We're going to rewrite the constraint to constrain the supertype roles, but assume they're the same:
895
- role_node = end_node
896
- end_role = role_ref.role
897
-
898
- # Create subtyping steps at the end-point, if needed:
899
- projecting_play = nil
900
- constrained_play = nil
901
- if (subtype = role_ref.role.object_type) != end_point
902
- trace :query, "Making subtyping steps from #{subtype.name} to #{end_point.name}" do
903
- # There may be more than one supertyping level. Make the steps:
904
- subtyping_steps = subtype_steps(query, subtype, end_point)
905
- step = subtyping_steps[0]
906
- #constrained_play = subtyping_steps[-1].all_play.detect{|p| p.role.object_type == end_point}
907
- subtyping_steps.detect{|s| constrained_play = s.all_play.detect{|p| p.role.object_type == end_point}}
908
-
909
- # Replace the constrained role and node with the supertype ones:
910
- end_node = query.all_variable.detect{|jn| jn.object_type == end_point }
911
- #projecting_play = step.all_play.detect{|p| p.role.object_type == subtype}
912
- subtyping_steps.detect{|s| projecting_play = s.all_play.detect{|p| p.role.object_type == subtype}}
913
- end_role = step.fact_type.all_role.detect{|r| r.object_type == end_point }
914
- role_node = query.all_variable.detect{|jn| jn.object_type == role_ref.role.object_type }
915
- end
916
- end
917
-
918
- if end_role.object_type != end_node.object_type
919
- raise "Internal error in #{constraint_type} #{name}: making illegal reference to variable, end role mismatch"
920
- end
921
-
922
- if join_over
923
- if !variable # Create the Variable when processing the first role
924
- trace :query, "Variable #{query.all_variable.size} is over #{join_over.name}"
925
- variable = @constellation.Variable(query, query.all_variable.size, :object_type => join_over)
926
- end
927
- trace :query, "Making step from #{end_point.name} to #{join_over.name}" do
928
- rs = @constellation.RoleSequence(:new)
929
- # Detect the fact type over which we're stepping (may involve objectification)
930
- raise "Internal error in #{constraint_type} #{name}: making illegal reference to variable, object type mismatch" if role_ref.role.object_type != role_node.object_type
931
- step = @constellation.Step(:guid => :new, :fact_type => joined_role.fact_type)
932
- @constellation.RoleRef(rs, 0, :role => role_ref.role)
933
- role_play = @constellation.Play(:step => step, :variable => role_node, :role => role_ref.role, :is_input => true)
934
- # Make the projected RoleRef:
935
- rr = @constellation.RoleRef(replacement_rs, replacement_rs.all_role_ref.size, :role => role_ref.role, :play => role_play)
936
- raise "Internal error in #{constraint_type} #{name}: making illegal reference to variable, joined_role mismatch" if joined_role.object_type != variable.object_type
937
- @constellation.RoleRef(rs, 1, :role => joined_role)
938
- join_play = @constellation.Play(:step => step, :variable => variable, :role => joined_role)
939
- trace :query, "New step #{step.describe}"
940
- end
941
- else
942
- trace :query, "Need step for non-join_over role #{end_point.name} #{role_ref.describe} in #{role_ref.role.fact_type.default_reading}"
943
- if (roles = role_ref.role.fact_type.all_role.to_a).size > 1
944
- # Here we have an end join (step already created) but no sequence join
945
- if variable
946
- raise "Internal error in #{constraint_type} #{name}: making illegal step" if role_ref.role.object_type != role_node.object_type
947
- step = @constellation.Step(:guid => :new, :fact_type => role_ref.role.fact_type)
948
- join_play = @constellation.Play(:step => step, :variable => variable, :role => query_role, :is_input => true)
949
- role_play = @constellation.Play(:step => step, :variable => role_node, :role => role_ref.role)
950
- # Make the projected RoleRef:
951
- rr = @constellation.RoleRef(replacement_rs, replacement_rs.all_role_ref.size, :role => role_ref.role, :play => role_play)
952
- roles -= [query_role, role_ref.role]
953
- roles.each do |incidental_role|
954
- jn = @constellation.Variable(query, query.all_variable.size, :object_type => incidental_role.object_type)
955
- play = @constellation.Play(:step => step, :variable => jn, :role => incidental_role, :step => step)
956
- end
957
- else
958
-
959
- if role_sequence.all_role_ref.size > 1
960
- variable = role_node
961
- query_role = role_ref.role
962
-
963
- # Make the projected RoleRef:
964
- rr = @constellation.RoleRef(replacement_rs, replacement_rs.all_role_ref.size, :role => constrained_play.role, :play => constrained_play)
965
- else
966
- # We enter this fact type (requiring that a role be played) but don't exit it.
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
- # There's no query in this role sequence, so we'd drop off the bottom without doing the right things. Why?
970
- # Without this case, Supervision.orm omits "that runs Company" from the exclusion constraint, and I'm not sure why.
971
- # 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)
972
- step = @constellation.Step(:guid => :new, :fact_type => role_ref.role.fact_type)
973
-
974
- # p constrained_play.role.object_type.name
975
- # p projecting_play.role.object_type.name
976
- # debugger
977
-
978
- role_play = @constellation.Play(:step => step, :variable => role_node, :role => role_ref.role, :is_input => true)
979
-
980
- # Make the projected RoleRef:
981
- rr = @constellation.RoleRef(replacement_rs, replacement_rs.all_role_ref.size, :role => constrained_play.role, :play => constrained_play)
982
-
983
- # role_ref.role.fact_type.all_role.each do |role|
984
- # next if role == role_play.role
985
- # next if role_sequence.all_role_ref.detect{|rr| rr.role == role}
986
- # jn = @constellation.Variable(query, query.all_variable.size, :object_type => role.object_type)
987
- # play = @constellation.Play(:step => step, :variable => jn, :role => role)
988
- # if role == role_ref.role
989
- # # Make the projected RoleRef:
990
- # rr = @constellation.RoleRef(replacement_rs, replacement_rs.all_role_ref.size, :role => role, :play => play)
991
- # end
992
- # end
993
-
994
- end
995
- end
996
- else
997
- # Unary fact type, make a Step from and to the constrained_play
998
- step = @constellation.Step(:guid => :new, :fact_type => role_ref.role.fact_type)
999
- play = @constellation.Play(:step => step, :variable => constrained_play.variable, :role => role_ref.role, :is_input => true)
1000
- # Make the projected RoleRef:
1001
- rr = @constellation.RoleRef(replacement_rs, replacement_rs.all_role_ref.size, :role => role_ref.role, :play => play)
1002
- end
1003
- end
1004
- end
1005
- raise "hell" if replacement_rs.all_role_ref.size != role_sequence.all_role_ref.size
1006
-
1007
- # Thoroughly check that this is a valid query
1008
- query.validate
1009
- trace :query, "Query has projected nodes #{replacement_rs.describe}"
1010
- replacement_rs
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 #{constraint_type} #{name} role sequence #{i}, there is a faulty join involving just 1 fact type: '#{fact_types[0].default_reading}'"
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
- # All roles in this set are played by the same object type
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 #{constraint_type} #{name} are incompatible (#{players.map(&:name)*', '})" if common_supertypes.size == 0
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, "#{constraint_type} join constraint #{name} over #{role_sequences.map{|rs|rs.describe}*', '}"
1071
+ trace :query, "#{constraint_desc} over #{role_sequences.map{|rs|rs.describe}*', '}"
1068
1072
 
1069
1073
  query = nil
1070
- trace :query, "#{constraint_type} join constraint #{name} constrains #{
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
- position = role_sequences.index(role_sequence)
1087
- replacement_rs = query_over_role_sequence(role_sequence, join_over, joined_roles, end_points)
1088
- if role_sequence != replacement_rs
1089
- role_sequences[position] = replacement_rs
1090
- end
1091
- end
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
- if role_sequences.compact.size != role_sequences.size # Role sequence missing; includes a derived fact type role
1128
- trace :orm, "skipped exclusion constraint #{id}, missing role sequence"
1129
- next
1130
- end
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
- unless make_queries('exclusion', name+(x_mandatory ? '/'+x_mandatory['Name'] : ''), role_sequences)
1133
- trace :orm, "skipped exclusion constraint #{id}, can't make_queries"
1134
- next
1135
- end
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
- # These are in the ORM file, but instead of using those,
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
- # REVISIT: This presumably duplicates the identifying fact instances for the above entities. Hmmm.
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, :location => location, :is_expanded => is_expanded,
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
- begin
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
- rescue =>e
1528
- debugger
1529
- @constellation.ReadingShape(:guid => id_of(xr_shape), :fact_type_shape => shape, :orm_diagram => diagram, :location => location, :is_expanded => false, :reading => fact_type.preferred_reading)
1530
- end
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)
@@ -1,5 +1,5 @@
1
1
  module ActiveFacts
2
2
  module ORM
3
- VERSION = "1.8.1"
3
+ VERSION = "1.9.1"
4
4
  end
5
5
  end
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.8.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: 2015-12-04 00:00:00.000000000 Z
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.2.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.