Class: ActiveFacts::Metamodel::Composite

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

Instance Method Summary collapse

Instance Method Details

#all_foreign_key_as_target_compositeObject



1708
1709
1710
1711
1712
# File 'lib/activefacts/metamodel/extensions.rb', line 1708

def all_foreign_key_as_target_composite
  all_access_path.
  select{|ap| ap.is_a?(ForeignKey)}.
  sort_by{|ap| ap.all_foreign_key_field.map(&:inspect) }
end

#all_indexObject



1656
1657
1658
1659
1660
# File 'lib/activefacts/metamodel/extensions.rb', line 1656

def all_index
  all_access_path.
  select{|ap| ap.is_a?(Index)}.
  sort_by{|ap| [ap.composite_as_primary_index ? 0 : 1] + Array(ap.name)+ap.all_index_field.map(&:inspect) }  # REVISIT: Fix hack for stable ordering
end

#all_indices_by_rankObject

Provide a stable ordering for indices, based on the ordering of columns by rank:



1702
1703
1704
1705
1706
# File 'lib/activefacts/metamodel/extensions.rb', line 1702

def all_indices_by_rank
  all_access_path.
  reject{|ap| ap.is_a?(ActiveFacts::Metamodel::ForeignKey)}.
  sort_by{|ap| ap.all_index_field.to_a.flat_map{|ixf| (c = ixf.component) ? c.rank_path : 0}.compact }
end

#inspectObject



1652
1653
1654
# File 'lib/activefacts/metamodel/extensions.rb', line 1652

def inspect
  "Composite #{mapping.inspect}"
end

#show_traceObject



1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
# File 'lib/activefacts/metamodel/extensions.rb', line 1662

def show_trace
  trace :composition, inspect do
    trace :composition?, "Columns" do
      mapping.show_trace
    end

    indices = all_index
    unless indices.empty?
      trace :composition, "Indices" do
        indices.each do |ap|
          ap.show_trace
        end
      end
    end

    inbound = all_access_path.
      select{|ap| ap.is_a?(ForeignKey)}.
      sort_by{|fk| [fk.source_composite.mapping.name, fk.mapping.inspect]+fk.all_foreign_key_field.map(&:inspect)+fk.all_index_field.map(&:inspect) }
    unless inbound.empty?
      trace :composition, "Foreign keys inbound" do
        inbound.each do |fk|
          fk.show_trace
        end
      end
    end

    outbound =
      all_foreign_key_as_source_composite.
      sort_by{|fk| [fk.source_composite.mapping.name, fk.mapping.inspect]+fk.all_index_field.map(&:inspect)+fk.all_foreign_key_field.map(&:inspect) }
    unless outbound.empty?
      trace :composition, "Foreign keys outbound" do
        outbound.each do |fk|
          fk.show_trace
        end
      end
    end
  end
end

#validate(&report) ⇒ Object



29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/activefacts/metamodel/validate/composition.rb', line 29

def validate &report
  trace :composition_validator?, "Validating #{inspect}" do
    report.call(self, "Has no Mapping") unless mapping
    report.call(self, "Mapping is not a mapping") unless mapping.class == Mapping
    report.call(mapping, "Has no ObjectType") unless mapping.object_type
    report.call(mapping, "Has no Name") unless mapping.name
    report.call(mapping, "Should not have an Ordinal rank") if mapping.ordinal
    report.call(mapping, "Should not have a parent mapping") if mapping.parent
    report.call(mapping, "Should be the root of its mapping") if mapping.root != self

    mapping.validate_members &report
    validate_access_paths &report
  end
end

#validate_access_paths(&report) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/activefacts/metamodel/validate/composition.rb', line 44

def validate_access_paths &report
  all_access_path.each do |access_path|
    report.call(access_path, "Must contain at least one IndexField") unless access_path.all_index_field.size > 0
    access_path.all_index_field.each do |index_field|
      report.call(access_path, "#{index_field.inspect} must be an Indicator or played by a ValueType") unless !index_field.component.is_a?(Mapping) || index_field.component.object_type.is_a?(ValueType)
      report.call(access_path, "#{index_field.inspect} must have a component") unless index_field.component
      if index_field.component
        report.call(access_path, "#{index_field.inspect} must be within its composite") unless index_field.component.root == self
      end
    end
    if ForeignKey === access_path
      if access_path.all_index_field.size == access_path.all_foreign_key_field.size
        access_path.all_index_field.to_a.zip(access_path.all_foreign_key_field.to_a).each do |index_field, foreign_key_field|
          report.call(access_path, "Column #{foreign_key_field.component.column_name}(#{foreign_key_field.component.class.basename}) does not match #{index_field.component.column_name}(#{index_field.component.class.basename})") unless index_field.component.class == foreign_key_field.component.class
          unless index_field.component.class == foreign_key_field.component.class
            report.call(access_path, "#{index_field.inspect} must have component type matching #{foreign_key_field.inspect}")
          else
            report.call(access_path, "#{index_field.inspect} must have matching target type") unless !index_field.component.is_a?(Absorption) or index_field.component.object_type == foreign_key_field.component.object_type
          end
          report.call(access_path, "#{foreign_key_field.inspect} must be within the source composite") unless foreign_key_field.component.root == access_path.source_composite
        end
      else
        report.call(access_path, "has #{access_path.all_index_field.size} index fields but #{access_path.all_foreign_key_field.size} ForeignKeyField")
      end
    end
  end
end