Class: ActiveFacts::CQL::Compiler::Reference
- Inherits:
-
Object
- Object
- ActiveFacts::CQL::Compiler::Reference
- Defined in:
- lib/activefacts/cql/compiler/clause.rb
Instance Attribute Summary collapse
-
#binding ⇒ Object
What Binding for that ObjectType.
-
#clause ⇒ Object
The clause that this Reference is part of.
-
#embedded_presence_constraint ⇒ Object
readonly
This refers to the ActiveFacts::Metamodel::PresenceConstraint.
-
#function_call ⇒ Object
readonly
Returns the value of attribute function_call.
-
#leading_adjective ⇒ Object
Returns the value of attribute leading_adjective.
-
#literal ⇒ Object
readonly
Returns the value of attribute literal.
-
#nested_clauses ⇒ Object
readonly
Returns the value of attribute nested_clauses.
-
#objectification_of ⇒ Object
If nested_clauses is set, this is the fact type it objectifies.
-
#player ⇒ Object
What ObjectType does the Binding denote.
-
#quantifier ⇒ Object
Returns the value of attribute quantifier.
-
#role ⇒ Object
Which Role of this ObjectType.
-
#role_name ⇒ Object
Returns the value of attribute role_name.
-
#role_ref ⇒ Object
Which RoleRef to that Role.
-
#term ⇒ Object
readonly
Returns the value of attribute term.
-
#trailing_adjective ⇒ Object
Returns the value of attribute trailing_adjective.
-
#value_constraint ⇒ Object
readonly
Returns the value of attribute value_constraint.
Instance Method Summary collapse
- #<=>(other) ⇒ Object
- #bind(context) ⇒ Object
- #compile(context) ⇒ Object
- #find_pc_over_roles(roles) ⇒ Object
- #identify_other_players(context) ⇒ Object
- #identify_player(context) ⇒ Object
- #identify_players_with_role_name(context) ⇒ Object
- #includes_literals ⇒ Object
-
#initialize(term, leading_adjective = nil, trailing_adjective = nil, quantifier = nil, function_call = nil, role_name = nil, value_constraint = nil, literal = nil, nested_clauses = nil) ⇒ Reference
constructor
A new instance of Reference.
- #inspect ⇒ Object
- #key ⇒ Object
- #make_embedded_presence_constraint(vocabulary) ⇒ Object
- #rebind(context) ⇒ Object
- #rebind_to(context, other_ref) ⇒ Object
- #result(context = nil) ⇒ Object
- #to_s ⇒ Object
- #unbind(context) ⇒ Object
- #uses_role_name? ⇒ Boolean
- #var_name ⇒ Object
-
#wipe_leading_adjective ⇒ Object
These are called when we successfully match a fact type reading that has relevant adjectives:.
- #wipe_trailing_adjective ⇒ Object
Constructor Details
#initialize(term, leading_adjective = nil, trailing_adjective = nil, quantifier = nil, function_call = nil, role_name = nil, value_constraint = nil, literal = nil, nested_clauses = nil) ⇒ Reference
Returns a new instance of Reference.
890 891 892 893 894 895 896 897 898 899 900 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 890 def initialize term, leading_adjective = nil, trailing_adjective = nil, quantifier = nil, function_call = nil, role_name = nil, value_constraint = nil, literal = nil, nested_clauses = nil @term = term @leading_adjective = leading_adjective @trailing_adjective = trailing_adjective @quantifier = quantifier # @function_call = function_call # Not used or implemented @role_name = role_name @value_constraint = value_constraint @literal = literal @nested_clauses = nested_clauses end |
Instance Attribute Details
#binding ⇒ Object
What Binding for that ObjectType
883 884 885 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 883 def binding @binding end |
#clause ⇒ Object
The clause that this Reference is part of
886 887 888 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 886 def clause @clause end |
#embedded_presence_constraint ⇒ Object (readonly)
This refers to the ActiveFacts::Metamodel::PresenceConstraint
888 889 890 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 888 def @embedded_presence_constraint end |
#function_call ⇒ Object (readonly)
Returns the value of attribute function_call.
880 881 882 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 880 def function_call @function_call end |
#leading_adjective ⇒ Object
Returns the value of attribute leading_adjective.
881 882 883 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 881 def leading_adjective @leading_adjective end |
#literal ⇒ Object (readonly)
Returns the value of attribute literal.
880 881 882 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 880 def literal @literal end |
#nested_clauses ⇒ Object (readonly)
Returns the value of attribute nested_clauses.
880 881 882 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 880 def nested_clauses @nested_clauses end |
#objectification_of ⇒ Object
If nested_clauses is set, this is the fact type it objectifies
887 888 889 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 887 def objectification_of @objectification_of end |
#player ⇒ Object
What ObjectType does the Binding denote
882 883 884 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 882 def player @player end |
#quantifier ⇒ Object
Returns the value of attribute quantifier.
881 882 883 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 881 def quantifier @quantifier end |
#role ⇒ Object
Which Role of this ObjectType
884 885 886 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 884 def role @role end |
#role_name ⇒ Object
Returns the value of attribute role_name.
881 882 883 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 881 def role_name @role_name end |
#role_ref ⇒ Object
Which RoleRef to that Role
885 886 887 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 885 def role_ref @role_ref end |
#term ⇒ Object (readonly)
Returns the value of attribute term.
880 881 882 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 880 def term @term end |
#trailing_adjective ⇒ Object
Returns the value of attribute trailing_adjective.
881 882 883 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 881 def trailing_adjective @trailing_adjective end |
#value_constraint ⇒ Object (readonly)
Returns the value of attribute value_constraint.
880 881 882 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 880 def value_constraint @value_constraint end |
Instance Method Details
#<=>(other) ⇒ Object
940 941 942 943 944 945 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 940 def <=>(other) ( 4*(@term <=> other.term) + 2*((@leading_adjective||'') <=> (other.leading_adjective||'')) + 1*((@trailing_adjective||'') <=> (other.trailing_adjective||'')) ) <=> 0 end |
#bind(context) ⇒ Object
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 995 def bind context @nested_clauses.each{|c| c.bind context} if @nested_clauses if role_name = @role_name # Omit these tests to see if anything evil eventuates: #if @leading_adjective || @trailing_adjective # raise "Role reference may not have adjectives if it defines a role name or uses a subscript: #{inspect}" #end else if uses_role_name? if @leading_adjective || @trailing_adjective raise "Role reference may not have adjectives if it uses a role name: #{inspect}" end role_name = @term end end k = key @binding = context.bindings[k] if !@binding if !literal # Find a binding that has a literal, and bind to it if it's the only one candidates = context.bindings.map do |binding_key, binding| binding_key[0...k.size] == k && binding_key[-2] == :literal ? binding : nil end.compact raise "Uncertain binding reference for #{to_s}, could be any of #{candidates.inspect}" if candidates.size > 1 @binding = candidates[0] else # New binding has a literal, look for one without: @binding = context.bindings[k[0...-2]] end end if !@binding @binding = Binding.new(@player, role_name) context.bindings[k] = @binding end @binding.add_ref self @binding end |
#compile(context) ⇒ Object
1135 1136 1137 1138 1139 1140 1141 1142 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 1135 def compile(context) identify_player(context) constellation = context.vocabulary.constellation constellation.Expression( :new, :expression_type => 'Role', :object_type => @player, :leading_adjective => leading_adjective, :trailing_adjective => trailing_adjective ) end |
#find_pc_over_roles(roles) ⇒ Object
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 1073 def find_pc_over_roles(roles) raise "No Role for embedded_presence_constraint" if roles.size == 0 # Safeguard; this would chuck an exception otherwise roles[0].all_role_ref.each do |role_ref| next if role_ref.role_sequence.all_role_ref.map(&:role) != roles pc = role_ref.role_sequence.all_presence_constraint.single # Will return nil if there's more than one. #puts "Existing PresenceConstraint matches those roles!" if pc return pc if pc end nil end |
#identify_other_players(context) ⇒ Object
962 963 964 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 962 def identify_other_players context identify_player context end |
#identify_player(context) ⇒ Object
966 967 968 969 970 971 972 973 974 975 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 966 def identify_player context @player || begin @player = context.object_type @term unless @player raise "ObjectType #{@term} unrecognised" end context.player_by_role_name[@role_name] = player if @role_name @player end end |
#identify_players_with_role_name(context) ⇒ Object
956 957 958 959 960 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 956 def identify_players_with_role_name(context) identify_player(context) if role_name # Include players in nested clauses, if any nested_clauses.each{|clause| clause.identify_players_with_role_name(context)} if nested_clauses end |
#includes_literals ⇒ Object
947 948 949 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 947 def includes_literals @nested_clauses && @nested_clauses.detect{|nested| nested.includes_literals} end |
#inspect ⇒ Object
902 903 904 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 902 def inspect to_s end |
#key ⇒ Object
981 982 983 984 985 986 987 988 989 990 991 992 993 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 981 def key if @role_name key = [@term, @role_name] # Defines a role name elsif uses_role_name? key = [@player.name, @term] # Uses a role name else l = @leading_adjective t = @trailing_adjective key = [!l || l.empty? ? nil : l, @term, !t || t.empty? ? nil : t] end key += [:literal, literal.literal] if @literal key end |
#make_embedded_presence_constraint(vocabulary) ⇒ Object
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 1084 def vocabulary return unless @role_ref fact_type = @role_ref.role.fact_type constellation = vocabulary.constellation trace :constraint, "Processing embedded constraint #{@quantifier.inspect} on #{@role_ref.role.object_type.name} in #{fact_type.describe}" do # Preserve the role order of the clause, excluding this role: constrained_roles = (@clause.refs-[self]).map{|vr| vr.role_ref.role} if constrained_roles.empty? trace :constraint, "Quantifier over unary role has no effect" return end constraint = find_pc_over_roles(constrained_roles) if constraint raise "Conflicting maximum frequency for constraint" if constraint.max_frequency && constraint.max_frequency != @quantifier.max trace :constraint, "Setting max frequency to #{@quantifier.max} for existing constraint #{constraint.object_id} over #{constraint.role_sequence.describe} in #{fact_type.describe}" unless constraint.max_frequency constraint.max_frequency = @quantifier.max raise "Conflicting minimum frequency for constraint" if constraint.min_frequency && constraint.min_frequency != @quantifier.min trace :constraint, "Setting min frequency to #{@quantifier.min} for existing constraint #{constraint.object_id} over #{constraint.role_sequence.describe} in #{fact_type.describe}" unless constraint.min_frequency constraint.min_frequency = @quantifier.min else role_sequence = constellation.RoleSequence(:new) constrained_roles.each_with_index do |constrained_role, i| role_ref = constellation.RoleRef(role_sequence, i, :role => constrained_role) end constraint = constellation.PresenceConstraint( :new, :vocabulary => vocabulary, :role_sequence => role_sequence, :is_mandatory => @quantifier.min && @quantifier.min > 0, # REVISIT: Check "maybe" qualifier? :max_frequency => @quantifier.max, :min_frequency => @quantifier.min ) if @quantifier.pragmas @quantifier.pragmas.each do |p| constellation.ConceptAnnotation(:concept => constraint.concept, :mapping_annotation => p) end end trace :constraint, "Made new embedded PC GUID=#{constraint.concept.guid} min=#{@quantifier.min.inspect} max=#{@quantifier.max.inspect} over #{(e = fact_type.entity_type) ? e.name : role_sequence.describe} in #{fact_type.describe}" @quantifier.enforcement.compile(constellation, constraint) if @quantifier.enforcement @embedded_presence_constraint = constraint end constraint end end |
#rebind(context) ⇒ Object
1045 1046 1047 1048 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 1045 def rebind(context) unbind context bind context end |
#rebind_to(context, other_ref) ⇒ Object
1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 1050 def rebind_to(context, other_ref) trace :binding, "Rebinding #{inspect} to #{other_ref.inspect}" old_binding = binding # Remember to move all refs across unbind(context) new_binding = other_ref.binding [self, *old_binding.refs].each do |ref| ref.binding = new_binding new_binding.add_ref ref end old_binding.rebound_to = new_binding end |
#result(context = nil) ⇒ Object
1131 1132 1133 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 1131 def result(context = nil) self end |
#to_s ⇒ Object
906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 906 def to_s "{#{ @quantifier && @quantifier.inspect+' ' }#{ @leading_adjective && @leading_adjective.sub(/ |$/,'- ').sub(/ *$/,' ') }#{ @term }#{ @trailing_adjective && ' '+@trailing_adjective.sub(/(.* |^)/, '\1-') }#{ @role_name and @role_name.is_a?(Integer) ? "(#{@role_name})" : " (as #{@role_name})" }#{ @literal && ' '+@literal.inspect }#{ @value_constraint && ' '+@value_constraint.to_s }}" end |
#unbind(context) ⇒ Object
1035 1036 1037 1038 1039 1040 1041 1042 1043 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 1035 def unbind context # The key has changed. @binding.delete_ref self if @binding.refs.empty? # Remove the binding from the context if this was the last reference context.bindings.delete_if {|k,v| v == @binding } end @binding = nil end |
#uses_role_name? ⇒ Boolean
977 978 979 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 977 def uses_role_name? @term != @player.name end |
#var_name ⇒ Object
924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 924 def var_name if @role_name && !@role_name.is_a?(Integer) @role_name else "#{ @leading_adjective && @leading_adjective.split.map(&:capitalize).join(' ') + ' ' }#{ @term }#{ @trailing_adjective && ' ' + @trailing_adjective.split.map(&:capitalize).join(' ') }#{ @role_name && "(#{@role_name})" }" end end |
#wipe_leading_adjective ⇒ Object
These are called when we successfully match a fact type reading that has relevant adjectives:
1065 1066 1067 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 1065 def wipe_leading_adjective @leading_adjective = nil end |
#wipe_trailing_adjective ⇒ Object
1069 1070 1071 |
# File 'lib/activefacts/cql/compiler/clause.rb', line 1069 def wipe_trailing_adjective @trailing_adjective = nil end |