class ActiveFacts::Generators::CQL

Generate CQL for an ActiveFacts vocabulary. Invoke as

afgen --cql <file>.cql

Private Instance Methods

append_ring_to_reading(reading, ring) click to toggle source
# File lib/activefacts/generators/cql.rb, line 75
def append_ring_to_reading(reading, ring)
  reading << " [#{(ring.ring_type.scan(/StronglyIntransitive|[A-Z][a-z]*/)*", ").downcase}]"
end
build_indices() click to toggle source
# File lib/activefacts/generators/cql.rb, line 616
def build_indices
  @presence_constraints_by_fact = Hash.new{ |h, k| h[k] = [] }
  @ring_constraints_by_fact = Hash.new{ |h, k| h[k] = [] }

  @vocabulary.all_constraint.each { |c|
      case c
      when ActiveFacts::Metamodel::PresenceConstraint
        fact_types = c.role_sequence.all_role_ref.map{|rr| rr.role.fact_type}.uniq  # All fact types spanned by this constraint
        if fact_types.size == 1     # There's only one, save it:
          # trace "Single-fact constraint on #{fact_types[0].concept.guid}: #{c.name}"
          (@presence_constraints_by_fact[fact_types[0]] ||= []) << c
        end
      when ActiveFacts::Metamodel::RingConstraint
        (@ring_constraints_by_fact[c.role.fact_type] ||= []) << c
      else
        # trace "Found unhandled constraint #{c.class} #{c.name}"
      end
    }
end
common_supertype(object_types) click to toggle source

Find the common supertype of these object_types.

# File lib/activefacts/generators/cql.rb, line 532
def common_supertype(object_types)
  common = object_types[0].supertypes_transitive
  object_types[1..-1].each do |object_type|
    common &= object_type.supertypes_transitive
  end
  common[0]
end
constraint_banner() click to toggle source
# File lib/activefacts/generators/cql.rb, line 345
def constraint_banner
  puts "/*\n * Constraints:"
  puts " */"
end
constraint_dump(c) click to toggle source
# File lib/activefacts/generators/cql.rb, line 516
def constraint_dump(c)
  case c
  when ActiveFacts::Metamodel::PresenceConstraint
    dump_presence_constraint(c)
  when ActiveFacts::Metamodel::RingConstraint
    dump_ring_constraint(c)
  when ActiveFacts::Metamodel::SetComparisonConstraint # includes SetExclusionConstraint, SetEqualityConstraint
    dump_set_comparison_constraint(c)
  when ActiveFacts::Metamodel::SubsetConstraint
    dump_subset_constraint(c)
  else
    "#{c.class.basename} #{c.name}: unhandled constraint type"
  end
end
constraint_end() click to toggle source
# File lib/activefacts/generators/cql.rb, line 350
def constraint_end
end
data_type_dump(o) click to toggle source
# File lib/activefacts/generators/cql.rb, line 47
def data_type_dump(o)
  value_type_dump(o, o.name, {}) if o.all_role.size > 0
end
detect_standard_refmode_readings(fact_type, entity_role, value_role) click to toggle source

This entity is identified by a single value, so find whether standard refmode readings were used

# File lib/activefacts/generators/cql.rb, line 112
def detect_standard_refmode_readings fact_type, entity_role, value_role
  forward_reading = reverse_reading = nil
  fact_type.all_reading.each do |reading|
    if reading.text =~ /^\{(\d)\} has \{\d\}$/
      if reading.role_sequence.all_role_ref.detect{|rr| rr.ordinal == $1.to_i}.role == entity_role
        forward_reading = reading
      else
        reverse_reading = reading
      end
    elsif reading.text =~ /^\{(\d)\} is of \{\d\}$/
      if reading.role_sequence.all_role_ref.detect{|rr| rr.ordinal == $1.to_i}.role == value_role
        reverse_reading = reading
      else
        forward_reading = reading
      end
    end
  end
  trace :mode, "Didn't find standard forward reading" unless forward_reading
  trace :mode, "Didn't find standard reverse reading" unless reverse_reading
  [forward_reading, reverse_reading]
end
dump_presence_constraint(c) click to toggle source
# File lib/activefacts/generators/cql.rb, line 361
def dump_presence_constraint(c)
  # Loose binding in PresenceConstraints is limited to explicit role players (in an occurs list)
  # having no exact match, but having instead exactly one role of the same player in the readings.

  verbaliser = ActiveFacts::CQL::Verbaliser.new
  # For a mandatory constraint (min_frequency == 1, max == nil or 1) any subtyping step is over the proximate role player
  # For all other presence constraints any subtyping step is over the counterpart player
  role_proximity = c.min_frequency == 1 && [nil, 1].include?(c.max_frequency) ? :proximate : :counterpart
  if role_proximity == :proximate
    verbaliser.role_refs_have_subtype_steps(c.role_sequence)
  else
    roles = c.role_sequence.all_role_ref.map{|rr|rr.role}
    join_over, joined_roles = ActiveFacts::Metamodel.plays_over(roles, role_proximity)
    verbaliser.roles_have_same_player(joined_roles) if join_over
  end

  verbaliser.prepare_role_sequence(c.role_sequence, join_over)
  # REVISIT: Need to discount role_adjuncts in here, since this constraint uses loose binding:
  verbaliser.create_subscripts :loose

  expanded_readings = verbaliser.verbalise_over_role_sequence(c.role_sequence, nil, role_proximity)
  if c.min_frequency == 1 && c.max_frequency == nil and c.role_sequence.all_role_ref.size == 2
    puts "either #{expanded_readings*' or '};"
  else
    roles = c.role_sequence.all_role_ref.map{|rr| rr.role }
    players = c.role_sequence.all_role_ref.map{|rr| verbaliser.subscripted_player(rr) }
    players.uniq! if role_proximity == :proximate
    min, max = c.min_frequency, c.max_frequency
    pl = (min&&min>1)||(max&&max>1) ? 's' : ''
    puts \
      "each #{players.size > 1 ? "combination " : ""}#{players*", "} occurs #{c.frequency} time#{pl} in\n\t"+
      "#{Array(expanded_readings)*",\n\t"};"
  end
end
dump_ring_constraint(c) click to toggle source
# File lib/activefacts/generators/cql.rb, line 511
def dump_ring_constraint(c)
  # At present, no ring constraint can be missed to be handled in this pass
  puts "// #{c.ring_type} ring over #{c.role.fact_type.default_reading}"
end
dump_set_comparison_constraint(c) click to toggle source
# File lib/activefacts/generators/cql.rb, line 396
def dump_set_comparison_constraint(c)
  scrs = c.all_set_comparison_roles.sort_by{|scr| scr.ordinal}
  role_sequences = scrs.map{|scr|scr.role_sequence}
  transposed_role_refs = scrs.map{|scr| scr.role_sequence.all_role_ref_in_order.to_a}.transpose
  verbaliser = ActiveFacts::CQL::Verbaliser.new

  # Tell the verbaliser all we know, so it can figure out which players to subscript:
  players = []
  trace :subscript, "Preparing query across projected roles in set comparison constraint" do
    transposed_role_refs.each do |role_refs|
      verbaliser.role_refs_have_subtype_steps role_refs
      join_over, = ActiveFacts::Metamodel.plays_over(role_refs.map{|rr| rr.role})
      players << join_over
    end
  end
  trace :subscript, "Preparing query between roles in set comparison constraint" do
    role_sequences.each do |role_sequence|
      trace :subscript, "role sequence is #{role_sequence.describe}" do
        verbaliser.prepare_role_sequence role_sequence
      end
    end
  end
  verbaliser.create_subscripts :normal

  if role_sequences.detect{|scr| scr.all_role_ref.detect{|rr| rr.play}}
    # This set constraint has an explicit query. Verbalise it.

    readings_list = role_sequences.
      map do |rs|
        verbaliser.verbalise_over_role_sequence(rs) 
      end
    if c.is_a?(ActiveFacts::Metamodel::SetEqualityConstraint)
      puts readings_list.join("\n\tif and only if\n\t") + ';'
      return
    end
    if readings_list.size == 2 && c.is_mandatory  # XOR constraint
      puts "either " + readings_list.join(" or ") + " but not both;"
      return
    end

    # Internal check: We must have located the players here
    if i = players.index(nil)
      rrs = transposed_role_refs[i]
      raise "Internal error detecting constrained object types in query involving #{rrs.map{|rr| rr.role.fact_type.default_reading}.uniq*', '}"
    end

    # Loose binding will apply only to the constrained roles, not to all roles. Not handled here.
    mode = c.is_mandatory ? "exactly one" : "at most one"
    puts "for each #{players.map{|p| p.name}*", "} #{mode} of these holds:\n\t" +
      readings_list.join(",\n\t") +
      ';'
    return
  end

  if c.is_a?(ActiveFacts::Metamodel::SetEqualityConstraint)
    puts \
      scrs.map{|scr|
        verbaliser.verbalise_over_role_sequence(scr.role_sequence)
      } * "\n\tif and only if\n\t" + ";"
    return
  end

  # A constrained role may involve a subtyping step. We substitute the name of the supertype for all occurrences.
  players = transposed_role_refs.map{|role_refs| common_supertype(role_refs.map{|rr| rr.role.object_type})}
  raise "Constraint must cover matching roles" if players.compact.size < players.size

  readings_expanded = scrs.
    map do |scr|
      # verbaliser.verbalise_over_role_sequence(scr.role_sequence)
      # REVISIT: verbalise_over_role_sequence cannot do what we need here, because of the
      # possibility of subtyping steps in the constrained roles across the different scr's
      # The following code uses "players" and "constrained_roles" to create substitutions.
      # These should instead be passed to the verbaliser (one variable per index, role_refs for each).
      fact_types_processed = {}
      constrained_roles = scr.role_sequence.all_role_ref_in_order.map{|rr| rr.role}
      join_over, joined_roles = *Metamodel.plays_over(constrained_roles)
      constrained_roles.map do |constrained_role|
        fact_type = constrained_role.fact_type
        next nil if fact_types_processed[fact_type] # Don't emit the same fact type twice (in case of objectification step)
        fact_types_processed[fact_type] = true
        reading = fact_type.reading_preferably_starting_with_role(constrained_role)
        expand_constrained(verbaliser, reading, constrained_roles, players)
      end.compact * " and "
    end

  if scrs.size == 2 && c.is_mandatory
    puts "either " + readings_expanded*" or " + " but not both;"
  else
    mode = c.is_mandatory ? "exactly one" : "at most one"
    puts "for each #{players.map{|p| p.name}*", "} #{mode} of these holds:\n\t" +
      readings_expanded*",\n\t" + ';'
  end
end
dump_subset_constraint(c) click to toggle source
# File lib/activefacts/generators/cql.rb, line 490
def dump_subset_constraint(c)
  # If the role players are identical and not duplicated, we can simply say "reading1 only if reading2"
  subset_roles, subset_fact_types =
    c.subset_role_sequence.all_role_ref_in_order.map{|rr| [rr.role, rr.role.fact_type]}.transpose
  superset_roles, superset_fact_types =
    c.superset_role_sequence.all_role_ref_in_order.map{|rr| [rr.role, rr.role.fact_type]}.transpose
  transposed_role_refs = [c.subset_role_sequence, c.superset_role_sequence].map{|rs| rs.all_role_ref_in_order.to_a}.transpose

  verbaliser = ActiveFacts::CQL::Verbaliser.new
  transposed_role_refs.each { |role_refs| verbaliser.role_refs_have_subtype_steps role_refs }
  verbaliser.prepare_role_sequence c.subset_role_sequence
  verbaliser.prepare_role_sequence c.superset_role_sequence
  verbaliser.create_subscripts :normal

  puts \
    verbaliser.verbalise_over_role_sequence(c.subset_role_sequence) +
    "\n\tonly if " +
    verbaliser.verbalise_over_role_sequence(c.superset_role_sequence) +
    ";"
end
entity_type_banner() click to toggle source
# File lib/activefacts/generators/cql.rb, line 239
def entity_type_banner
  puts "/*\n * Entity Types\n */"
end
entity_type_dump(o) click to toggle source
# File lib/activefacts/generators/cql.rb, line 60
def entity_type_dump(o)
  o.ordered_dumped!
  pi = o.preferred_identifier

  supers = o.supertypes
  if (supers.size > 0)
    # Ignore identification by a supertype:
    pi = nil if pi && pi.role_sequence.all_role_ref.detect{|rr| rr.role.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance) }
    subtype_dump(o, supers, pi)
  else
    non_subtype_dump(o, pi)
  end
  pi.ordered_dumped! if pi
end
entity_type_group_end() click to toggle source
# File lib/activefacts/generators/cql.rb, line 243
def entity_type_group_end
  puts "\n"
end
expand_constrained(verbaliser, reading, constrained_roles, players) click to toggle source

Expand this reading, substituting players.name for the each role in the i'th position in constrained_roles

# File lib/activefacts/generators/cql.rb, line 600
def expand_constrained(verbaliser, reading, constrained_roles, players)
  # Make sure that we refer to the constrained players by their common supertype (as passed in)
  frequency_constraints = reading.role_sequence.all_role_ref.
    map do |role_ref|
      player = role_ref.role.object_type
      i = constrained_roles.index(role_ref.role)
      player = players[i] if i
      [ nil, player.name ]
    end
  frequency_constraints = [] unless frequency_constraints.detect{|fc| fc[0] != "some" }

  expanded = verbaliser.expand_reading(reading, frequency_constraints)
  expanded = "it is not the case that "+expanded if (reading.is_negative)
  expanded
end
expanded_reading(verbaliser, reading, fact_constraints, define_role_names) click to toggle source
# File lib/activefacts/generators/cql.rb, line 555
def expanded_reading(verbaliser, reading, fact_constraints, define_role_names)
  # Arrange the roles in order they occur in this reading:
  role_refs = reading.role_sequence.all_role_ref_in_order
  role_numbers = reading.text.scan(/\{(\d)\}/).flatten.map{|m| Integer(m) }
  roles = role_numbers.map{|m| role_refs[m].role }

  # Find the constraints that constrain frequency over each role we can verbalise:
  frequency_constraints = []
  value_constraints = []
  roles.each do |role|
    value_constraints <<
      if vc = role.role_value_constraint and !vc.ordered_dumped
        vc.ordered_dumped!
        vc.describe
      else
        nil
      end

    frequency_constraints <<
      if (role == roles.last)   # On the last role of the reading, emit any presence constraint
        constraint = fact_constraints.
          detect do |c|  # Find a UC that spans all other Roles
            c.is_a?(ActiveFacts::Metamodel::PresenceConstraint) &&
              !c.ordered_dumped &&  # Already verbalised
              roles-c.role_sequence.all_role_ref.map(&:role) == [role]
          end
        constraint.ordered_dumped! if constraint
        constraint && constraint.frequency
      else
        nil
      end
  end

  expanded = verbaliser.expand_reading(reading, frequency_constraints, define_role_names, value_constraints)
  expanded = "it is not the case that "+expanded if (reading.is_negative)

  if (ft_rings = @ring_constraints_by_fact[reading.fact_type]) &&
     (ring = ft_rings.detect{|rc| !rc.ordered_dumped})
    ring.ordered_dumped!
    append_ring_to_reading(expanded, ring)
  end
  expanded
end
fact_readings_with_constraints(verbaliser, fact_type) click to toggle source
Verbalisation functions for fact type and entity type definitions
# File lib/activefacts/generators/cql.rb, line 544
def fact_readings_with_constraints(verbaliser, fact_type)
  fact_constraints = @presence_constraints_by_fact[fact_type]
  readings = []
  define_role_names = true
  fact_type.all_reading_by_ordinal.each do |reading|
    readings << expanded_reading(verbaliser, reading, fact_constraints, define_role_names)
    define_role_names = false     # No need to define role names in subsequent readings
  end
  readings
end
fact_type_banner() click to toggle source
# File lib/activefacts/generators/cql.rb, line 337
def fact_type_banner
  puts "/*\n * Fact Types\n */"
end
fact_type_dump(fact_type, name) click to toggle source
# File lib/activefacts/generators/cql.rb, line 281
def fact_type_dump(fact_type, name)

  if (o = fact_type.entity_type)
    print "#{o.name} is"
    supertypes = o.supertypes
    if supertypes.empty?
      print ' independent' if o.is_independent
    else
      print " a kind of#{
          o.is_independent ? ' independent' : ''
        } #{ supertypes.map(&:name)*', ' }"
    end

    # Alternate identification of objectified fact type?
    primary_supertype = supertypes[0]
    if fact_type.all_role.size > 1 and
        pi = fact_type.entity_type.preferred_identifier and
        primary_supertype && primary_supertype.preferred_identifier != pi
      puts identified_by(o, pi) + ';'
      return
    end
    print " where\n\t"
  end

  # Check whether this fact type has readings which could be confused for a previously-dumped one:
  reading_texts = fact_type.all_reading.map{|r| naiive_expand(r)}
  if reading_texts.size > 1
    ambiguity =
      fact_type.all_role.to_a[0].object_type.all_role.map{|r| r.fact_type}.
        select{|f| f != fact_type && f.ordered_dumped }.
        detect do |dft|
          ambiguous_readings =
            reading_texts & dft.all_reading.map{|r| naiive_expand(r)}
          ambiguous_readings.size > 0
        end
    if ambiguity
      puts fact_type.default_reading([], true)+';  // Avoid ambiguity; this is a new fact type'
    end
  end

  # There can be no roles of the objectified fact type in the readings, so no need to tell the Verbaliser anything special
  verbaliser = ActiveFacts::CQL::Verbaliser.new
  verbaliser.alternate_readings fact_type.all_reading
  pr = fact_type.preferred_reading
  if (pr.role_sequence.all_role_ref.to_a[0].play)
    verbaliser.prepare_role_sequence pr.role_sequence
  end
  verbaliser.create_subscripts(:rolenames)

  print(fact_readings_with_constraints(verbaliser, fact_type)*",\n\t")
  if (pr.role_sequence.all_role_ref.to_a[0].play)
    print " where\n\t"+verbaliser.verbalise_over_role_sequence(pr.role_sequence)
  end
  puts(';')
end
fact_type_end() click to toggle source
# File lib/activefacts/generators/cql.rb, line 341
def fact_type_end
  puts "\n"
end
identified_by_ref_mode(entity_type, identifying_facts) click to toggle source

If this entity_type is identified by a reference mode, return the verbalisation

# File lib/activefacts/generators/cql.rb, line 135
def identified_by_ref_mode(entity_type, identifying_facts)
  fact_type, entity_role, value_role, value_residual =
    *value_role_identification(entity_type, identifying_facts)
  return nil unless fact_type

  # This EntityType is identified by its association with a single ValueType
  # whose name is an extension (the value_residual) of the EntityType's name.
  # If we have at least one of the standard refmode readings, dump it that way,
  # else exit and use the long-hand verbalisation instead.

  forward_reading, reverse_reading =
    *detect_standard_refmode_readings(fact_type, entity_role, value_role)
  return nil unless (forward_reading || reverse_reading)

  # We can't subscript reference modes.
  # If an objectified fact type has a role played by its identifying player, go long-hand.
  return nil if entity_type.fact_type and
    entity_type.fact_type.all_role.detect{|role| role.object_type == value_role.object_type }

  fact_type.ordered_dumped!  # We've covered this fact type

  # Elide the constraints that would have been emitted on the standard readings.
  # If there is a UC that's not in the standard form for a reference mode,
  # we have to emit the standard reading anyhow.
  fact_constraints = @presence_constraints_by_fact[fact_type]
  fact_constraints.each do |pc|
    if (pc.role_sequence.all_role_ref.size == 1 and pc.max_frequency == 1)
      # It's a uniqueness constraint, and will be regenerated
      pc.ordered_dumped!
    end
  end

  # Figure out which non-standard readings exist, if any:
  nonstandard_readings = fact_type.all_reading - [forward_reading, reverse_reading]
  trace :mode, "--- nonstandard_readings.size now = #{nonstandard_readings.size}" if nonstandard_readings.size > 0

  verbaliser = ActiveFacts::CQL::Verbaliser.new

  # The verbaliser needs to have a Player for the roles of entity_type, so it doesn't get subscripted.
  entity_roles =
    nonstandard_readings.map{|r| r.role_sequence.all_role_ref.detect{|rr| rr.role.object_type == entity_type}}.compact
  verbaliser.role_refs_have_same_player entity_roles

  verbaliser.alternate_readings nonstandard_readings
  if entity_type.fact_type
    verbaliser.alternate_readings entity_type.fact_type.all_reading
  end

  verbaliser.create_subscripts(:rolenames)      # Ok, the Verbaliser is ready to fly

  fact_readings =
    nonstandard_readings.map { |reading| expanded_reading(verbaliser, reading, fact_constraints, true) }
  fact_readings +=
    fact_readings_with_constraints(verbaliser, entity_type.fact_type) if entity_type.fact_type

  # If we emitted a reading for the refmode, it'll include any role_value_constraint already
  if nonstandard_readings.size == 0 and c = value_role.role_value_constraint
    constraint_text = " "+c.as_cql
  end
  (entity_type.is_independent ? ' independent' : '') +
    " identified by its #{value_residual}#{constraint_text}#{mapping_pragma(entity_type, true)}" +
    entity_type.concept.all_context_note_as_relevant_concept.map do |cn|
      cn.verbalise
    end.join("\n") +
    (fact_readings.size > 0 ? " where\n\t" : "") +
    fact_readings*",\n\t"
end
identified_by_roles_and_facts(entity_type, identifying_role_refs, identifying_facts) click to toggle source
# File lib/activefacts/generators/cql.rb, line 203
def identified_by_roles_and_facts(entity_type, identifying_role_refs, identifying_facts)
  # Detect standard reference-mode scenarios:
  if srm = identified_by_ref_mode(entity_type, identifying_facts)
    return srm
  end

  verbaliser = ActiveFacts::CQL::Verbaliser.new

  # Announce all the identifying fact roles to the verbaliser so it can decide on any necessary subscripting.
  # The verbaliser needs to have a Player for the roles of entity_type, so it doesn't get subscripted.
  entity_roles =
    identifying_facts.map{|ft| ft.preferred_reading.role_sequence.all_role_ref.detect{|rr| rr.role.object_type == entity_type}}.compact
  verbaliser.role_refs_have_same_player entity_roles
  identifying_facts.each do |fact_type|
    # The RoleRefs for corresponding roles across all readings are for the same player.
    verbaliser.alternate_readings fact_type.all_reading
    fact_type.ordered_dumped! unless fact_type.entity_type # Must dump objectification still!
  end
  verbaliser.create_subscripts(:rolenames)

  irn = verbaliser.identifying_role_names identifying_role_refs

  identifying_fact_text = 
      identifying_facts.map{|f|
          fact_readings_with_constraints(verbaliser, f)
      }.flatten*",\n\t"

  (entity_type.is_independent ? ' independent' : '') +
    " identified by #{ irn*" and " }" +
    mapping_pragma(entity_type, true) +
    entity_type.concept.all_context_note_as_relevant_concept.map do |cn|
      cn.verbalise
    end.join("\n") +
    " where\n\t"+identifying_fact_text
end
mapping_pragma(entity_type, ignore_independence = false) click to toggle source
# File lib/activefacts/generators/cql.rb, line 79
def mapping_pragma(entity_type, ignore_independence = false)
  ti = entity_type.all_type_inheritance_as_subtype
  assimilation = ti.map{|t| t.assimilation }.compact[0]
  return "" unless (entity_type.is_independent && !ignore_independence) || assimilation
  " [" +
    [
      entity_type.is_independent && !ignore_independence ? "independent" : nil,
      assimilation || nil
    ].compact*", " +
  "]"
end
naiive_expand(reading) click to toggle source
# File lib/activefacts/generators/cql.rb, line 274
def naiive_expand(reading)
  role_refs = reading.role_sequence.all_role_ref_in_order
  reading.text.gsub(/\{(\d+)\}/) do
    role_refs[$1.to_i].role.object_type.name
  end
end
non_subtype_dump(o, pi) click to toggle source
# File lib/activefacts/generators/cql.rb, line 270
def non_subtype_dump(o, pi)
  puts "#{o.name} is" + identified_by(o, pi) + ';'
end
roleplayer_subclass(roles) click to toggle source

Of the players of a set of roles, return the one that's a subclass of (or same as) all others, else nil

# File lib/activefacts/generators/cql.rb, line 354
def roleplayer_subclass(roles)
  roles[1..-1].inject(roles[0].object_type){|subclass, role|
    next nil unless subclass and EntityType === role.object_type
    role.object_type.supertypes_transitive.include?(subclass) ? role.object_type : nil
  }
end
subtype_dump(o, supertypes, pi) click to toggle source
# File lib/activefacts/generators/cql.rb, line 247
def subtype_dump(o, supertypes, pi)
  print "#{o.name} is a kind of #{
      o.is_independent ? 'independent ' : ''
    }#{ o.supertypes.map(&:name)*", " }"
  if pi
    puts identified_by(o, pi)+';'
    return
  end

  print mapping_pragma(o, true)

  if o.fact_type
    verbaliser = ActiveFacts::CQL::Verbaliser.new
    # Announce all the objectified fact roles to the verbaliser so it can decide on any necessary subscripting.
    # The RoleRefs for corresponding roles across all readings are for the same player.
    verbaliser.alternate_readings o.fact_type.all_reading
    verbaliser.create_subscripts(:rolenames)

    print " where\n\t" + fact_readings_with_constraints(verbaliser, o.fact_type)*",\n\t"
  end
  puts ";\n"
end
unit_dump(unit) click to toggle source
# File lib/activefacts/generators/cql.rb, line 31
def unit_dump unit
  puts unit.as_cql
end
units_banner() click to toggle source
# File lib/activefacts/generators/cql.rb, line 27
def units_banner
  puts "/*\n * Units\n */"
end
units_end() click to toggle source
# File lib/activefacts/generators/cql.rb, line 35
def units_end
  puts "\n"
end
value_role_identification(entity_type, identifying_facts) click to toggle source

If this entity_type is identified by a single value, return four relevant objects:

# File lib/activefacts/generators/cql.rb, line 92
def value_role_identification(entity_type, identifying_facts)
  external_identifying_facts = identifying_facts - [entity_type.fact_type]
  fact_type = external_identifying_facts[0]
  ftr = fact_type && fact_type.all_role.sort_by{|role| role.ordinal}
  if external_identifying_facts.size == 1 and
      entity_role = ftr[n = (ftr[0].object_type == entity_type ? 0 : 1)] and
      value_role = ftr[1-n] and
      value_player = value_role.object_type and
      value_player.is_a?(ActiveFacts::Metamodel::ValueType) and
      value_name = value_player.name and
      value_residual = value_name.sub(%r{^#{entity_role.object_type.name} ?},'') and
      value_residual != '' and
      value_residual != value_name
    [fact_type, entity_role, value_role, value_residual]
  else
    []
  end
end
value_type_banner() click to toggle source
# File lib/activefacts/generators/cql.rb, line 39
def value_type_banner
  puts "/*\n * Value Types\n */"
end
value_type_dump(o, super_type_name, facets) click to toggle source
# File lib/activefacts/generators/cql.rb, line 51
def value_type_dump(o, super_type_name, facets)
  # No need to dump it if the only thing it does is be a supertype; it'll be created automatically
  # return if o.all_value_type_as_supertype.size == 0

  # REVISIT: A ValueType that is only used as a reference mode need not be emitted here.

  puts o.as_cql
end
value_type_end() click to toggle source
# File lib/activefacts/generators/cql.rb, line 43
def value_type_end
  puts "\n"
end
vocabulary_end() click to toggle source
# File lib/activefacts/generators/cql.rb, line 24
def vocabulary_end
end
vocabulary_start() click to toggle source
# File lib/activefacts/generators/cql.rb, line 19
def vocabulary_start
  puts "vocabulary #{@vocabulary.name};\n\n"
  build_indices
end