Class: ActiveFacts::CQL::Compiler::RingConstraint

Inherits:
Constraint show all
Defined in:
lib/activefacts/cql/compiler/constraint.rb

Constant Summary collapse

Types =
%w{acyclic intransitive stronglyintransitive symmetric asymmetric transitive antisymmetric irreflexive reflexive}
Pairs =
{
  :stronglyintransitive => [:acyclic, :asymmetric, :symmetric],
  :intransitive => [:acyclic, :asymmetric, :symmetric],
  :transitive => [:acyclic],
  :acyclic => [:transitive],
  :irreflexive => [:symmetric]
}

Instance Attribute Summary

Attributes inherited from Definition

#constellation, #tree, #vocabulary

Instance Method Summary collapse

Methods inherited from Constraint

#bind_clauses, #common_bindings, #loose_bind, #loose_bind_wherever_possible, #loose_binding, #warn_ignored_queries

Methods inherited from Definition

#all_bindings_in_clauses, #build_all_steps, #build_steps, #build_variables, #source

Constructor Details

#initialize(role_sequence, qualifiers) ⇒ RingConstraint

Returns a new instance of RingConstraint.



436
437
438
439
440
441
# File 'lib/activefacts/cql/compiler/constraint.rb', line 436

def initialize role_sequence, qualifiers
  super nil, nil
  @role_sequence = role_sequence
  @rings, rest = qualifiers.partition{|q| Types.include?(q) }
  qualifiers.replace rest
end

Instance Method Details

#compileObject



443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
# File 'lib/activefacts/cql/compiler/constraint.rb', line 443

def compile
  # Process the ring constraints:
  return if @rings.empty?

  role_refs = @role_sequence.all_role_ref_in_order.to_a
  supertypes_by_position = role_refs.
    map do |role_ref|
      role_ref.role.object_type.supertypes_transitive
    end
  role_pairs = []
  supertypes_by_position.each_with_index do |sts, i|
    (i+1...supertypes_by_position.size).each do |j|
      common_supertype = (sts & supertypes_by_position[j])[0]
      role_pairs << [role_refs[i], role_refs[j], common_supertype] if common_supertype
    end
  end
  if role_pairs.size > 1
    # REVISIT: Verbalise the role_refs better:
    raise "ambiguous #{@rings*' '} ring constraint, consider #{role_pairs.map{|rp| "#{rp[0].inspect}<->#{rp[1].inspect}"}*', '}"
  end
  if role_pairs.size == 0
    raise "No matching role pair found for #{@rings*' '} ring constraint over #{role_refs.map(&:role).map(&:object_type).map(&:name).inspect}"
  end

  rp = role_pairs[0]

  # Ensure that the keys in Pairs follow others:
  @rings = @rings.partition{|rc| !Pairs.keys.include?(rc.downcase.to_sym) }.flatten

  if @rings.size > 1 and !(p = Pairs[@rings[-1].to_sym]) and !p.include?(@rings[0].to_sym)
    raise "incompatible ring constraint types (#{@rings*", "})"
  end
  ring_type = @rings.map{|c| c.capitalize}*""

  @constraint = @constellation.RingConstraint(
      :new,
      :vocabulary => @vocabulary,
  #   :name => name,              # Create a name for Ring Constraints?
      :role => rp[0].role,
      :other_role => rp[1].role,
      :ring_type => ring_type
    )

  debug :constraint, "Added #{@constraint.verbalise}"
  super
end

#to_sObject



490
491
492
# File 'lib/activefacts/cql/compiler/constraint.rb', line 490

def to_s
  "#{super} #{@rings*','} over #{@clauses_lists.inspect}"
end