class ActiveFacts::Metamodel::Absorption

Public Instance Methods

all_role() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1981
def all_role
  ([child_role, parent_role] + all_nesting.map(&:index_role)).flat_map{|role| [role, role.base_role]}.uniq
end
comment() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1998
def comment
  return '' unless parent
  prefix = parent.comment
  reading = parent_role.fact_type.reading_preferably_starting_with_role(parent_role).expand([], false)
  maybe = parent_role.is_mandatory ? '' : 'maybe '
  parent_name = parent.name
  if prefix[(-parent_name.size-1)..-1] == ' '+parent_name && reading[0..parent_name.size] == parent_name+' '
    prefix+' that ' + maybe + reading[parent_name.size+1..-1]
  else
    (prefix.empty? ? '' : prefix+' and ') + maybe + reading
  end
end
flip!() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1966
def flip!
  raise "REVISIT: Need to flip FullAbsorption on #{inspect}" if full_absorption or reverse_mapping && reverse_mapping.full_absorption or forward_mapping && forward_mapping.full_absorption
  if (other = forward_mapping)
    # We point at them - make them point at us instead
    self.forward_mapping = nil
    self.reverse_mapping = other
  elsif (other = reverse_mapping)
    # They point at us - make us point at them instead
    self.reverse_mapping = nil
    self.forward_mapping = other
  else
    raise "Absorption cannot be flipped as it has no reverse"
  end
end
inspect() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1871
def inspect
  "#{super}#{full_absorption ? ' (full)' : ''
  } in #{inspect_reason}#{
    # If we have a related forward absorption, we're by definition a reverse absorption
    if forward_mapping
      ' (reverse)'
     else
        # If we have a related reverse absorption, we're by definition a forward absorption
        reverse_mapping ? ' (forward)' : ''
    end
  }"
end
inspect_reason() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1867
def inspect_reason
  parent_role.fact_type.reading_preferably_starting_with_role(parent_role).expand.inspect
end
is_mandatory() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1990
def is_mandatory
  parent_role.is_mandatory
end
is_one_to_one() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1910
def is_one_to_one
  parent_role.is_unique and child_role.is_unique
end
is_partitioned_here() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1906
def is_partitioned_here
  (ft = child_role.fact_type).is_a?(TypeInheritance) && ft.assimilation == 'partitioned'
end
is_preferred_direction() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1914
def is_preferred_direction
  return child_role.is_mirror_role if child_role.is_mirror_role != parent_role.is_mirror_role

  # Prefer to absorb the one into the many:
  p_un = parent_role.is_unique
  c_un = child_role.is_unique
  return p_un if p_un != c_un

  # Prefer to absorb a subtype into the supertype (opposite if separate or partitioned)
  if (ti = child_role.fact_type).is_a?(TypeInheritance)
    is_subtype = child_role == ti.subtype_role  # Supertype absorbing subtype
    subtype = ti.subtype_role.object_type       # Subtype doesn't want to be absorbed?
    # REVISIT: We need fewer ways to say this:
    child_separate = ["separate", "partitioned"].include?(ti.assimilation) ||
      subtype.is_independent ||
      subtype.concept.all_concept_annotation.detect{|ca| ca.mapping_annotation == 'separate'}
    return !is_subtype != !child_separate
  end

  if p_un && c_un
    # Prefer to absorb a ValueType into an EntityType rather than the other way around:
    pvt = parent_role.object_type.is_a?(ActiveFacts::Metamodel::ValueType)
    cvt = child_role.object_type.is_a?(ActiveFacts::Metamodel::ValueType)
    return cvt if pvt != cvt

    if !pvt
      # Force the decision if one EntityType identifies another
      return true if child_role.base_role.is_identifying  # Parent is identified by child role, correct
      return false if parent_role.base_role.is_identifying # Child is identified by parent role, incorrect
    end

    # Primary absorption absorbs the object playing the mandatory role into the non-mandatory:
    return child_role.is_mandatory if !parent_role.is_mandatory != !child_role.is_mandatory
  end

  if parent_role.object_type.is_a?(ActiveFacts::Metamodel::EntityType) &&
       child_role.object_type.is_a?(ActiveFacts::Metamodel::EntityType)
    # Prefer to absorb an identifying element into the EntityType it identifies
    return true if parent_role.object_type.preferred_identifier.
      role_sequence.all_role_ref.map(&:role).detect{|r|
        r.object_type == child_role.object_type
      }
    return false if child_role.object_type.preferred_identifier.
      role_sequence.all_role_ref.map(&:role).detect{|r|
        r.object_type == parent_role.object_type
      }
  end

  # For stability, absorb a later-named role into an earlier-named one:
  return parent_role.name < child_role.name
end
is_subtype_absorption() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1902
def is_subtype_absorption
  is_type_inheritance && parent_role.fact_type.supertype == object_type
end
is_supertype_absorption() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1898
def is_supertype_absorption
  is_type_inheritance && child_role.fact_type.supertype == object_type
end
is_type_inheritance() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1894
def is_type_inheritance
  child_role.fact_type.is_a?(TypeInheritance) && child_role.fact_type
end
path_mandatory() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1994
def path_mandatory
  is_mandatory && parent.path_mandatory
end
show_trace() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1884
def show_trace
  super() do
    if nesting_mode || all_nesting.size > 0
      trace :composition, "Nested using #{nesting_mode || 'unspecified'} mode" do
        all_nesting.sort_by(&:ordinal).each(&:show_trace)
      end
    end
  end
end
validate_nesting(&report) click to toggle source
# File lib/activefacts/metamodel/validate/composition.rb, line 135
def validate_nesting &report
  report.call(self, "REVISIT: Unexpected and unchecked Nesting")
  report.call(self, "Nesting Mode must be specified") unless self.nesting_mode
  # REVISIT: Nesting names must be unique
  # REVISIT: Nesting roles must be played by...
  # REVISIT: Nesting roles must be value types
end
value_constraints() click to toggle source
# File lib/activefacts/metamodel/extensions.rb, line 1985
def value_constraints
  return [] unless object_type.is_a?(ValueType)
  object_type.supertypes_transitive.flat_map{|vt| Array(vt.value_constraint)}
end