module ActiveFacts::API::ObjectType

Public Instance Methods

__absorb(prefix, except_role = nil) click to toggle source

Return an array of the absorbed columns, using prefix for name truncation

# File lib/activefacts/rmap/object_type.rb, line 64
def __absorb(prefix, except_role = nil)
  # also considered a table if the superclass isn't excluded and is (transitively) a table
  if !@is_table && (except_role == superclass || !is_table_subtype)
    if is_entity_type
      if (role = fully_absorbed) && role != except_role
        # If this non-table is fully absorbed into another table (not our caller!)
        # (another table plays its single identifying role), then absorb that role only.
        # counterpart_object_type = role.counterpart_object_type
        # This omission matches the one in columns.rb, see EntityType#reference_columns
        # new_prefix = prefix + [role.name.to_s.split(/_/)]
        trace :rmap, "Reference to #{role.name} (absorbed elsewhere)" do
          role.counterpart_object_type.__absorb(prefix, role.counterpart)
        end
      else
        # Not a table -> all roles are absorbed
        roles.
            values.
            select do |role|
              role.unique && role != except_role && !role.counterpart_unary_has_precedence
            end.
            inject([]) do |columns, role|
          columns += __absorb_role(prefix, role)
        end +
        subtypes.          # Absorb subtype roles too!
          select{|subtype| !subtype.is_table}.    # Don't absorb separate subtypes
          inject([]) do |columns, subtype|
            # Pass self as 2nd param here, not a role, standing for the supertype role
            new_prefix = prefix[0..-2] + [[subtype.basename]]
            trace :rmap, "Absorbed subtype #{subtype.basename}" do
              columns += subtype.__absorb(new_prefix, self)
            end
          end
      end
    else
      [prefix]
    end
  else
    # Create a foreign key to the table
    if is_entity_type
      ir = identifying_role_names.map{|role_name| roles(role_name) }
      trace :rmap, "Reference to #{basename} with #{prefix.inspect}" do
        ic = identifying_role_names.map{|role_name| role_name.to_s.split(/_/)}
        ir.inject([]) do |columns, role|
          columns += __absorb_role(prefix, role)
        end
      end
    else
      # Reference to value type which is a table
      col = prefix.clone
      trace :rmap, "Self-value #{col[-1]}.Value"
      col[-1] += ["Value"]
      col
    end
  end
end
__absorb_role(prefix, role) click to toggle source
# File lib/activefacts/rmap/object_type.rb, line 120
def __absorb_role(prefix, role)
  if prefix.size > 0 and
      (c = role.owner).is_entity_type and
      c.identifying_roles == [role] and
      (irn = c.identifying_role_names).size == 1 and
      (n = irn[0].to_s.split(/_/)).size > 1 and
      (owner = role.owner.basename.snakecase.split(/_/)) and
      n[0...owner.size] == owner
    trace :rmap, "truncating transitive identifying role #{n.inspect}"
    owner.size.times { n.shift }
    new_prefix = prefix + [n]
  elsif (c = role.counterpart_object_type).is_entity_type and
      (irn = c.identifying_role_names).size == 1 and
      #irn[0].to_s.split(/_/)[0] == role.owner.basename.downcase
      irn[0] == role.counterpart.name
    #trace :rmap, "=== #{irn[0].to_s.split(/_/)[0]} elided ==="
    new_prefix = prefix
  elsif (fa_role = fully_absorbed) && fa_role == role
    new_prefix = prefix
  else
    new_prefix = prefix + [role.name.to_s.split(/_/)]
  end
  #trace :rmap, "new_prefix is #{new_prefix*"."}"

  trace :rmap, "Absorbing role #{role.name} as #{new_prefix[prefix.size..-1]*"."}" do
    role.counterpart_object_type.__absorb(new_prefix, role.counterpart)
  end
end
columns() click to toggle source
# File lib/activefacts/rmap/object_type.rb, line 14
      def columns
raise "This method is no longer in use"
=begin
        return @columns if @columns
        trace :rmap, "Calculating columns for #{basename}" do
          @columns = (
            if superclass.is_entity_type
              # REVISIT: Need keys to secondary supertypes as well, but no duplicates.
              trace :rmap, "Separate subtype has a foreign key to its supertype" do
                superclass.__absorb([[superclass.basename]], self)
              end
            else
              []
            end +
            # Then absorb all normal roles:
            roles.values.select do |role|
              role.unique && !role.counterpart_unary_has_precedence
            end.inject([]) do |columns, role|
              rn = role.name.to_s.split(/_/)
              trace :rmap, "Role #{rn*'.'}" do
                columns += role.counterpart_object_type.__absorb([rn], role.counterpart)
              end
            end +
            # And finally all absorbed subtypes:
            subtypes.
              select{|subtype| !subtype.is_table}.    # Don't absorb separate subtypes
              inject([]) do |columns, subtype|
                # Pass self as 2nd param here, not a role, standing for the supertype role
                subtype_name = subtype.basename
                trace :rmap, "Absorbing subtype #{subtype_name}" do
                  columns += subtype.__absorb([[subtype_name]], self)
                end
              end
            ).map do |col_names|
              last = nil
              col_names.flatten.map do |name|
                name.downcase.sub(/^[a-z]/){|c| c.upcase}
              end.
              reject do |n|
                # Remove sequential duplicates:
                dup = last == n
                last = n
                dup
              end*"."
            end
        end
=end
      end
is_table() click to toggle source
# File lib/activefacts/rmap/object_type.rb, line 10
def is_table
  @is_table
end
is_table_subtype() click to toggle source
# File lib/activefacts/rmap/object_type.rb, line 149
def is_table_subtype
  return true if is_table
  klass = superclass
  while klass.is_entity_type
    return true if klass.is_table
    klass = klass.superclass
  end
  return false
end
table() click to toggle source
# File lib/activefacts/rmap/object_type.rb, line 6
def table
  @is_table = true
end