Class: ActiveFacts::Metamodel::Mapping

Inherits:
Component
  • Object
show all
Defined in:
lib/activefacts/metamodel/metamodel.rb,
lib/activefacts/metamodel/extensions.rb,
lib/activefacts/metamodel/validate/composition.rb

Direct Known Subclasses

Absorption, Injection, Scoping, TemporalMapping

Constant Summary

Constants inherited from Component

Component::RANK_DISCRIMINATOR, Component::RANK_FOREIGN, Component::RANK_IDENT, Component::RANK_INDICATOR, Component::RANK_INJECTION, Component::RANK_MANDATORY, Component::RANK_MULTIPLE, Component::RANK_NON_MANDATORY, Component::RANK_SCOPING, Component::RANK_SUBTYPE, Component::RANK_SUPER, Component::RANK_SURROGATE, Component::RANK_VALUE

Instance Method Summary collapse

Methods inherited from Component

#all_role, #comment, #data_type, #depth, #fork_to_new_parent, #in_foreign_key, #in_primary_index, #leaves, #narrow_value_constraint, #parent_entity_type, #path, #primary_index_components, #rank_key, #rank_kind, #rank_path, #uncache_rank_key

Instance Method Details

#all_leafObject



1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
# File 'lib/activefacts/metamodel/extensions.rb', line 1802

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

#inspectObject



1773
1774
1775
# File 'lib/activefacts/metamodel/extensions.rb', line 1773

def inspect
  "#{self.class.basename} (#{rank_kind})#{parent ? " in #{parent.name}" :''} of #{name && name != '' ? name : '<anonymous>'}"
end

#is_auto_assignedObject



1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
# File 'lib/activefacts/metamodel/extensions.rb', line 1821

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_mandatoryObject



1813
1814
1815
# File 'lib/activefacts/metamodel/extensions.rb', line 1813

def is_mandatory
  true
end

#path_mandatoryObject



1817
1818
1819
# File 'lib/activefacts/metamodel/extensions.rb', line 1817

def path_mandatory
  true
end

#re_rankObject

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



1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
# File 'lib/activefacts/metamodel/extensions.rb', line 1787

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

#rootObject



1798
1799
1800
# File 'lib/activefacts/metamodel/extensions.rb', line 1798

def root
  composite || parent && parent.root
end

#show_traceObject



1777
1778
1779
1780
1781
1782
1783
1784
# File 'lib/activefacts/metamodel/extensions.rb', line 1777

def show_trace
  trace :composition, "#{ordinal ? "#{ordinal}: " : ''}#{inspect}" do
    yield if block_given?
    all_member.sort_by{|member| [member.ordinal, member.name]}.each do |member|
      member.show_trace
    end
  end
end

#validate_members(&report) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/activefacts/metamodel/validate/composition.rb', line 71

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_reverse &report
        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 Injection
        report.call(member, "REVISIT: Unexpected and unchecked Injection")

      when Mapping
        report.call(member, "A child Component should not be a bare Mapping")

      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