class ActiveFacts::Metamodel::Mapping

Public Instance Methods

all_leaf() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1822
def all_leaf
  re_rank
  all_member.sort_by(&:ordinal).flat_map do |member|
    if member.is_a?(Mapping) && member.all_member.size > 0
      member.all_leaf
    else
      member
    end
  end
end
inspect() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1785
def inspect
  "#{self.class.basename} (#{rank_kind})#{parent ? " in #{parent.name}" :''} of #{name && name != '' ? name : '<anonymous>'}"
end
inspect_reason() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1781
def inspect_reason
  "#{parent.name} contains mapping of #{name}"
end
is_auto_assigned() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1841
def is_auto_assigned
  # It's auto-assigned if it's an auto-assigned value type and it's in its root's primary_index and is not a foreign key field
  if root and
      (a = object_type.is_auto_assigned) and
      (root.primary_index.all_index_field.detect{|ixf| ixf.component == self}) and
      (!all_foreign_key_field.detect{|fkf| fkf.foreign_key.source_composite == self.root})
    a
  else
    nil
  end
end
is_mandatory() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1833
def is_mandatory
  true
end
is_partitioned_here() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1853
def is_partitioned_here
  false # Must be an absorption to be partitioned here
end
is_type_inheritance() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1802
def is_type_inheritance
  false
end
path_mandatory() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1837
def path_mandatory
  !parent || parent.path_mandatory
end
re_rank() click to toggle source

Recompute a contiguous member ranking fron zero, based on current membership:

# File lib/activefacts/metamodel/extensions.rb, line 1807
def re_rank
  all_member.each(&:uncache_rank_key)
  next_rank = 0
  all_member.
  sort_by(&:rank_key).
  each do |member|
    member.ordinal = next_rank
    next_rank += 1
  end
end
root() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1818
def root
  composite || parent && parent.root
end
show_trace() { || ... } click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1789
def show_trace
  trace :composition, "#{ordinal ? "#{ordinal}: " : ''}#{inspect}" do
    yield if block_given?
    if m = all_member.detect{|m| !m.ordinal}
      trace :composition, "WARNING: show_trace needed to re_rank #{name} because of unranked #{m.inspect}"
      re_rank
    end
    all_member.sort_by{|member| [member.ordinal, member.name]}.each do |member|
      member.show_trace
    end
  end
end
validate_members(&report) click to toggle source
# File lib/activefacts/metamodel/validate/composition.rb, line 74
def validate_members &report
  # Names (except of subtype/supertype absorption) must be unique:
  names = all_member.
    reject{|m| m.is_a?(Absorption) && m.parent_role.fact_type.is_a?(TypeInheritance)}.
    map(&:name).
    compact
  duplicate_names = names.select{|name| names.count(name) > 1}.uniq
  report.call(self, "Contains duplicated names #{duplicate_names.map(&:inspect)*', '}") unless duplicate_names.empty?

  all_member.each do |member|
    trace :composition_validator?, "Validating #{member.inspect}" do
      report.call(member, "Requires a name") unless Absorption === member && member.flattens or member.name && !member.name.empty?
      case member
      when Absorption
        p = member.parent_role
        c = member.child_role
        report.call(member, "Roles should belong to the same fact type, but instead we have #{p.name} in #{p.fact_type.default_reading} and #{c.name} in #{c.fact_type.default_reading}") unless p.fact_type == c.fact_type
        report.call(member, "Object type #{member.object_type.name} should play the child role #{c.name}") unless member.object_type == c.object_type
        report.call(member, "Parent mapping object type #{object_type.name} should play the parent role #{p.name}") unless object_type == p.object_type

        member.validate_nesting &report if member.all_nesting.size > 0
        member.validate_members &report

      when Scoping
        report.call(member, "REVISIT: Unexpected and unchecked Scoping")

      when ValueField
        # Nothing to check here

      when SurrogateKey
        # Nothing to check here

      when ValidFrom
        # Nothing to check here

      when Mapping
        member.validate_reverse &report

      when Indicator
        report.call(member, "Indicator requires a Role") unless member.role

      when Discriminator
        report.call(member, "Discriminator requires at least one Discriminated Role") if member.all_discriminated_role.empty?
        member.all_discriminated_role.each do |role|
          report.call(member, "Discriminated Role #{role.name} is not played by parent object type #{object_type.name}") unless role.object_type == object_type
        end
        # REVISIT: Discriminated Roles must have distinct values matching the type of the Role
      end
    end
  end
end
validate_reverse(&report) click to toggle source
# File lib/activefacts/metamodel/validate/composition.rb, line 126
def validate_reverse &report
  reverse = forward_mapping || reverse_mapping
  return unless reverse
  report.call(self, "Opposite absorption's child role #{reverse.child_role.name} should match parent role #{parent_role.name}") unless reverse.child_role == parent_role
  report.call(self, "Opposite absorption's parent role #{reverse.parent_role.name} should match child role #{child_role.name}") unless reverse.parent_role == child_role
end