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

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

Constant Summary collapse

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

Instance Attribute Summary

Attributes inherited from Definition

#constellation, #source, #vocabulary

Instance Method Summary collapse

Methods inherited from Constraint

#all_bindings_in_readings, #bind_readings, #common_bindings, #loose_bind_roles, #loose_bind_wherever_possible, #loose_binding, #warn_ignored_joins

Constructor Details

#initialize(role_sequence, qualifiers) ⇒ RingConstraint

Returns a new instance of RingConstraint.



556
557
558
559
560
561
# File 'lib/activefacts/cql/compiler/constraint.rb', line 556

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



563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
# File 'lib/activefacts/cql/compiler/constraint.rb', line 563

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

  role_refs = @role_sequence.all_role_ref.to_a
  supertypes_by_position = role_refs.
    map do |role_ref|
      role_ref.role.concept.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"
  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 !Pairs[@rings[-1].to_sym].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} #{@constraint.class.roles.keys.map{|k|"#{k} => "+@constraint.send(k).verbalise}*", "}"
  super
end