Class: ActiveFacts::CQL::Compiler::Definition
- Inherits:
-
Object
- Object
- ActiveFacts::CQL::Compiler::Definition
- Defined in:
- lib/activefacts/cql/compiler/query.rb,
lib/activefacts/cql/compiler/shared.rb
Direct Known Subclasses
Instance Attribute Summary collapse
-
#constellation ⇒ Object
Returns the value of attribute constellation.
-
#tree ⇒ Object
Returns the value of attribute tree.
-
#vocabulary ⇒ Object
Returns the value of attribute vocabulary.
Instance Method Summary collapse
-
#all_bindings_in_clauses(clauses) ⇒ Object
Return the unique array of all bindings in these clauses, including in objectification steps.
- #build_all_steps(clauses_list) ⇒ Object
- #build_steps(clause, roles_by_binding = {}, objectification_node = nil) ⇒ Object
-
#build_variables(clauses_list) ⇒ Object
Make a Variable for every binding present in these clauses.
- #compile ⇒ Object
- #source ⇒ Object
- #to_s ⇒ Object
Instance Attribute Details
#constellation ⇒ Object
Returns the value of attribute constellation.
86 87 88 |
# File 'lib/activefacts/cql/compiler/shared.rb', line 86 def constellation @constellation end |
#tree ⇒ Object
Returns the value of attribute tree.
86 87 88 |
# File 'lib/activefacts/cql/compiler/shared.rb', line 86 def tree @tree end |
#vocabulary ⇒ Object
Returns the value of attribute vocabulary.
86 87 88 |
# File 'lib/activefacts/cql/compiler/shared.rb', line 86 def vocabulary @vocabulary end |
Instance Method Details
#all_bindings_in_clauses(clauses) ⇒ Object
Return the unique array of all bindings in these clauses, including in objectification steps
165 166 167 168 169 170 171 172 173 174 |
# File 'lib/activefacts/cql/compiler/query.rb', line 165 def all_bindings_in_clauses clauses clauses.map do |clause| clause.refs.map do |ref| raise "Binding reference #{ref.inspect} is not bound to a binding" unless ref.binding [ref.binding] + (ref.nested_clauses ? all_bindings_in_clauses(ref.nested_clauses) : []) end end. flatten. uniq end |
#build_all_steps(clauses_list) ⇒ Object
26 27 28 29 30 31 32 33 34 35 |
# File 'lib/activefacts/cql/compiler/query.rb', line 26 def build_all_steps(clauses_list) roles_by_binding = {} debug :query, "Building steps" do clauses_list.each do |clause| next if clause.is_naked_object_type build_steps(clause, roles_by_binding) end end roles_by_binding end |
#build_steps(clause, roles_by_binding = {}, objectification_node = nil) ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/activefacts/cql/compiler/query.rb', line 37 def build_steps clause, roles_by_binding = {}, objectification_node = nil plays = [] incidental_roles = [] debug :query, "Creating Role Sequence for #{clause.inspect} with #{clause.refs.size} role refs" do objectification_step = nil clause.refs.each do |ref| # These refs are the Compiler::References, which have associated Metamodel::RoleRefs, # but we need to create Plays for those roles. # REVISIT: Plays may need to save residual_adjectives binding = ref.binding role = (ref && ref.role) || (ref.role_ref && ref.role_ref.role) play = nil debugger unless clause.fact_type if (clause.fact_type.entity_type) # This clause is of an objectified fact type. # We need a step from this role to the phantom role, but not # for a role that has only one ref (this one) in their binding. # Create the Variable and Play in any case though. refs_count = binding.refs.size objectification_ref_count = 0 if ref.nested_clauses ref.nested_clauses.each do |ojc| objectification_ref_count += ojc.refs.select{|ref| ref.binding.refs.size > 1}.size end end refs_count += objectification_ref_count debug :query, "Creating Variable #{ref.inspect} (counts #{refs_count}/#{objectification_ref_count}) and objectification Step for #{ref.inspect}" do raise "Internal error: Trying to add role of #{role.object_type.name} to variable for #{binding.variable.object_type.name}" unless binding.variable.object_type == role.object_type play = @constellation.Play(binding.variable, role) if (refs_count <= 1) # Our work here is done if there are no other refs if objectification_step play.step = objectification_step else incidental_roles << play end next end plays << play unless objectification_node # This is an implicit objectification, just the FT clause, not ET(where ...clause...) # We need to create a Variable for this object, even though it has no References query = binding.variable.query debug :query, "Creating JN#{query.all_variable.size} for #{clause.fact_type.entity_type.name} in objectification" objectification_node = @constellation.Variable(query, query.all_variable.size, :object_type => clause.fact_type.entity_type) end raise "Internal error: Trying to add role of #{role.link_fact_type.all_role.single.object_type.name} to variable for #{objectification_node.object_type.name}" unless objectification_node.object_type == role.link_fact_type.all_role.single.object_type irole = role.link_fact_type.all_role.single raise "Internal error: Trying to add role of #{irole.object_type.name} to variable for #{objectification_node.object_type.name}" unless objectification_node.object_type == irole.object_type objectification_role = @constellation.Play(objectification_node, role.link_fact_type.all_role.single) objectification_step = @constellation.Step( objectification_role, play, :fact_type => role.link_fact_type, :is_optional => false, :is_disallowed => clause.certainty == false ) if clause.certainty == nil objectification_step.is_optional = true end debug :query, "New #{objectification_step.describe}" debug :query, "Associating #{incidental_roles.map(&:describe)*', '} incidental roles with #{objectification_step.describe}" if incidental_roles.size > 0 incidental_roles.each { |jr| jr.step = objectification_step } incidental_roles = [] plays = [] end else debug :query, "Creating Reference for #{ref.inspect}" do # REVISIT: If there's an implicit subtyping step here, create it; then always raise the error here. # I don't want to do this for now because the verbaliser will always verbalise all steps. if binding.variable.object_type != role.object_type and 0 == (binding.variable.object_type.supertypes_transitive & role.object_type.supertypes_transitive).size raise "Internal error: Trying to add role of #{role.object_type.name} to variable #{binding.variable.ordinal} for #{binding.variable.object_type.name} in '#{clause.fact_type.default_reading}'" end raise "Internal error: Trying to add role of #{role.object_type.name} to variable #{binding.variable.ordinal} for #{binding.variable.object_type.name}" unless binding.variable.object_type == role.object_type begin play = @constellation.Play(binding.variable, role) rescue ArgumentError => e play = @constellation.Play(binding.variable, role) end plays << play end end if ref.nested_clauses # We are looking at a role whose player is an objectification of a fact type, # which will have ImplicitFactTypes for each role. # Each of these ImplicitFactTypes has a single phantom role played by the objectifying entity type # One of these phantom roles is likely to be the subject of an objectification step. ref.nested_clauses.each do |r| debug :query, "Building objectification step for #{ref.nested_clauses.inspect}" do build_steps r, roles_by_binding, binding.variable end end end roles_by_binding[binding] = [role, play] end end if plays.size > 0 end_node = plays[-1].variable if !clause.fact_type.entity_type and role = clause.fact_type.all_role.single # Don't give the ImplicitBoolean a variable. We can live without one, for now. # The Step will have a duplicate node, and the fact type will tell us what's happening plays << plays[0] end # We aren't talking about objectification here, so there must be exactly two roles. raise "REVISIT: Internal error constructing step for #{clause.inspect}" if plays.size != 2 js = @constellation.Step( plays[0], plays[1], :fact_type => clause.fact_type, :is_disallowed => clause.certainty == false, :is_optional => clause.certainty == nil ) debug :query, "New #{js.describe}" debug :query, "Associating #{incidental_roles.map(&:describe)*', '} incidental roles with #{js.describe}" if incidental_roles.size > 0 incidental_roles.each { |jr| jr.step = js } end roles_by_binding end |
#build_variables(clauses_list) ⇒ Object
Make a Variable for every binding present in these clauses
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/activefacts/cql/compiler/query.rb', line 6 def build_variables(clauses_list) debug :query, "Building variables" do query = @constellation.Query(:new) all_bindings_in_clauses(clauses_list). each do |binding| debug :query, "Creating variable #{query.all_variable.size} for #{binding.inspect}" binding.variable = @constellation.Variable(query, query.all_variable.size, :object_type => binding.player) if literal = binding.refs.detect{|r| r.literal} if literal.kind_of?(ActiveFacts::CQL::Compiler::Reference) # REVISIT: Fix this crappy ad-hoc polymorphism hack literal = literal.literal end unit = @constellation.Unit.detect{|k, v| [v.name, v.plural_name].include? literal.unit} if literal.unit binding.variable.value = [literal.literal.to_s, literal.literal.is_a?(String), unit] end end query end end |
#compile ⇒ Object
87 88 89 |
# File 'lib/activefacts/cql/compiler/shared.rb', line 87 def compile raise "#{self.class} should implement the compile method" end |
#source ⇒ Object
95 96 97 |
# File 'lib/activefacts/cql/compiler/shared.rb', line 95 def source @tree.text_value end |
#to_s ⇒ Object
91 92 93 |
# File 'lib/activefacts/cql/compiler/shared.rb', line 91 def to_s @vocabulary ? "#{vocabulary.to_s}::" : '' end |