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 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.