lib/activefacts/cql/compiler/reading.rb in activefacts-0.8.8 vs lib/activefacts/cql/compiler/reading.rb in activefacts-0.8.9

- old
+ new

@@ -5,10 +5,13 @@ class Reading attr_reader :phrases attr_accessor :qualifiers, :context_note attr_reader :fact_type, :reading, :role_sequence # These are the Metamodel objects attr_reader :side_effects + attr_writer :fact_type # Assigned for a bare (existential) objectification fact + attr_accessor :fact # When binding fact instances the fact goes here + attr_accessor :objectified_as # The Reading::RoleRef which objectified this fact type def initialize role_refs_and_words, qualifiers = [], context_note = nil @phrases = role_refs_and_words role_refs.each { |role_ref| role_ref.reading = self } @qualifiers = qualifiers @@ -25,10 +28,20 @@ @phrases.size == 1 and @phrases[0].is_a?(RoleRef) and !@phrases[0].literal end + def display + "#{ + @qualifiers && @qualifiers.size > 0 ? @qualifiers.inspect+' ' : nil + }#{ + @phrases.map{|p| p.to_s }*" " + }#{ + @context_note && ' '+@context_note.inspect + }" + end + def inspect "#{@qualifiers && @qualifiers.size > 0 ? @qualifiers.inspect+' ' : nil}#{@phrases.map{|p|p.inspect}*" "}#{@context_note && ' '+@context_note.inspect}" end def identify_players_with_role_name context @@ -46,11 +59,11 @@ role_ref.objectification_join.each{|reading| reading.identify_other_players(context)} if role_ref.objectification_join end end def includes_literals - role_refs.detect{|role_ref| role_ref.literal } + role_refs.detect{|role_ref| role_ref.literal || (ja = role_ref.objectification_join and ja.detect{|jr| jr.includes_literals })} end def bind_roles context role_names = role_refs.map{ |role_ref| role_ref.role_name }.compact @@ -83,10 +96,11 @@ # It returns nil if there is none, or a ReadingMatchSideEffects object if matched. # # As this match may not necessarily be used (depending on the side effects), # no change is made to this Reading object - those will be done later. def match_existing_fact_type context + raise "Internal error, reading already matched, should not match again" if @fact_type rrs = role_refs players = rrs.map{|rr| rr.player} raise "Must identify players before matching fact types" if players.include? nil raise "A fact type must involve at least one object type, but there are none in '#{inspect}'" if players.size == 0 @@ -95,17 +109,20 @@ debug :matching, "Looking for existing #{players.size}-ary fact types matching '#{inspect}'" do debug :matching, "Players are '#{player_names.inspect}'" # Match existing fact types in objectification joins first: rrs.each do |role_ref| - next unless objectification_join = role_ref.objectification_join && role_ref.objectification_join[0] - objectified_fact_type = - objectification_join.match_existing_fact_type(context) - raise "Unrecognised fact type #{objectification_join.inspect} in #{self.class}" unless objectified_fact_type - objectified_as = objectified_fact_type.entity_type - raise "Fact type #{objectification_join.reading.expand} is not objectified as #{role_ref.inspect}" unless objectified_as || objectified_as != role_ref.player - role_ref.objectification_of = objectified_fact_type + next unless joins = role_ref.objectification_join and !joins.empty? + role_ref.objectification_join.each do |oj| + ft = oj.match_existing_fact_type(context) + raise "Unrecognised fact type #{oj.display}" unless ft + if (ft && ft.entity_type == role_ref.player) + role_ref.objectification_of = ft + oj.objectified_as = role_ref + end + end + raise "#{role_ref.inspect} contains objectification joins that do not objectify it" unless role_ref.objectification_of end # For each role player, find the compatible types (the set of all subtypes and supertypes). # For a player that's an objectification, we don't allow implicit supertype joins player_related_types = @@ -669,9 +686,19 @@ @literal && ' '+@literal.inspect }#{ @value_constraint && ' '+@value_constraint.inspect }#{ @objectification_join ? "(where #{@objectification_join.inspect})" : "" }>" + end + + def to_s + "#{ + @quantifier && @quantifier.inspect+' ' }#{ + @leading_adjective && @leading_adjective.sub(/ |$/,'- ').sub(/ *$/,' ') }#{ + @role_name || @term }#{ + @trailing_adjective && ' '+@trailing_adjective.sub(/(.* |^)/, '\1-') }#{ + @literal && ' '+@literal.inspect }#{ + @value_constraint && ' '+@value_constraint.inspect }" end def <=>(other) ( 4*(@term <=> other.term) + 2*((@leading_adjective||'') <=> (other.leading_adjective||'')) +