class ActiveFacts::Metamodel::Reading

Public Instance Methods

expand(frequency_constraints = [], define_role_names = nil, literals = [], &subscript_block) click to toggle source

The frequency_constraints array here, if supplied, may provide for each role either:

  • a PresenceConstraint to be verbalised against the relevant role, or

  • a String, used as a definite or indefinite article on the relevant role, or

  • an array containing two strings (an article and a super-type name)

The order in the array is the same as the reading's role-sequence. REVISIT: This should probably be changed to be the fact role sequence.

define_role_names here is false (use defined names), true (define names) or nil (neither)

# File lib/activefacts/metamodel/extensions.rb, line 896
def expand(frequency_constraints = [], define_role_names = nil, literals = [], &subscript_block)
  expanded = "#{text}"
  role_refs = role_sequence.all_role_ref.sort_by{|role_ref| role_ref.ordinal}
  (0...role_refs.size).each{|i|
      role_ref = role_refs[i]
      role = role_ref.role
      l_adj = "#{role_ref.leading_adjective}".sub(/(\b-\b|.\b|.\Z)/, '\1-').sub(/\b--\b/,'-- ').sub(/- /,'-  ')
      l_adj = nil if l_adj == ""
      # Double the space to compensate for space removed below
      t_adj = "#{role_ref.trailing_adjective}".sub(/\w+$/,' -\0').sub(/--\w*$/, ' \0')
      t_adj = nil if t_adj == ""

      expanded.gsub!(/\{#{i}\}/) do
          role_ref = role_refs[i]
          if role_ref.role
            player = role_ref.role.object_type
            role_name = role.role_name
            role_name = nil if role_name == ""
            if role_name && define_role_names == false
              l_adj = t_adj = nil   # When using role names, don't add adjectives
            end

            freq_con = frequency_constraints[i]
            freq_con = freq_con.frequency if freq_con && freq_con.is_a?(ActiveFacts::Metamodel::PresenceConstraint)
            if freq_con.is_a?(Array)
              freq_con, player_name = *freq_con
            else
              player_name = player.name
            end
          else
            # We have an unknown role. The reading cannot be correctly expanded
            player_name = "UNKNOWN"
            role_name = nil
            freq_con = nil
          end

          literal = literals[i]
          words = [
            freq_con ? freq_con : nil,
            l_adj,
            define_role_names == false && role_name ? role_name : player_name,
            t_adj,
            define_role_names && role_name && player_name != role_name ? "(as #{role_name})" : nil,
            # Can't have both a literal and a value constraint, but we don't enforce that here:
            literal ? literal : nil
          ]
          if (subscript_block)
            words = subscript_block.call(role_ref, *words)
          end
          words.compact*" "
      end
  }
  expanded.gsub!(/ ?- ?/, '-')        # Remove single spaces around adjectives
  #trace "Expanded '#{expanded}' using #{frequency_constraints.inspect}"
  expanded
end
expand_with_final_presence_constraint(&b) click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 971
def expand_with_final_presence_constraint &b
  # Arrange the roles in order they occur in this reading:
  role_refs = role_sequence.all_role_ref_in_order
  role_numbers = text.scan(/\{(\d)\}/).flatten.map{|m| Integer(m) }
  roles = role_numbers.map{|m| role_refs[m].role }
  fact_constraints = fact_type.internal_presence_constraints

  # Find the constraints that constrain frequency over each role we can verbalise:
  frequency_constraints = []
  roles.each do |role|
    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) &&
              roles-c.role_sequence.all_role_ref.map(&:role) == [role]
          end
        constraint && constraint.frequency
      else
        nil
      end
  end

  expand(frequency_constraints) { |*a| b && b.call(*a) }
end
role_numbers() click to toggle source

Return the array of the numbers of the RoleRefs inserted into this reading from the role_sequence

# File lib/activefacts/metamodel/extensions.rb, line 967
def role_numbers
  text.scan(/\{(\d)\}/).flatten.map{|m| Integer(m) }
end
words_and_role_refs() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 953
def words_and_role_refs
  text.
  scan(/(?: |\{[0-9]+\}|[^{} ]+)/).   # split up the text into words
  reject{|s| s==' '}.                 # Remove white space
  map do |frag|                       # and go through the bits
    if frag =~ /\{([0-9]+)\}/
      role_sequence.all_role_ref.detect{|rr| rr.ordinal == $1.to_i}
    else
      frag
    end
  end
end