lib/activefacts/vocabulary/extensions.rb in activefacts-0.6.0 vs lib/activefacts/vocabulary/extensions.rb in activefacts-0.7.0

- old
+ new

@@ -38,10 +38,20 @@ pc.max_frequency == 1 } } end + def is_mandatory + all_role_ref.detect{|rr| + rs = rr.role_sequence + rs.all_role_ref.size == 1 and + rs.all_presence_constraint.detect{|pc| + pc.min_frequency and pc.min_frequency >= 1 and pc.is_mandatory + } + } + end + # Return the RoleRef to this role from its fact type's preferred_reading def preferred_reference fact_type.preferred_reading.role_sequence.all_role_ref.detect{|rr| rr.role == self } end end @@ -71,10 +81,23 @@ else role.role_name || [leading_adjective, role.concept.name, trailing_adjective].compact.map{|w| w.split(/\s/)}.flatten end return joiner ? Array(name_array)*joiner : Array(name_array) end + + # Two RoleRefs are equal if they have the same role and JoinPaths with matching roles + def ==(role_ref) + RoleRef === role_ref && + role_ref.role == role && + all_join_path.size == role_ref.all_join_path.size && + !all_join_path.sort_by{|j|j.join_step}. + zip(role_ref.all_join_path.sort_by{|j|j.join_step}). + detect{|j1,j2| + j1.input_role != j2.input_role || + j1.output_role != j2.output_role + } + end end class RoleSequence def describe "("+ @@ -105,13 +128,27 @@ fact_roles[0,2].each{|r| # Try the first two roles of the fact type, that's enough r.all_role_ref.map{|rr| # All role sequences that reference this role role_sequence = rr.role_sequence # The role sequence is only interesting if it cover only this fact's roles + # or roles of the objectification next if role_sequence.all_role_ref.size < fact_roles.size-1 # Not enough roles next if role_sequence.all_role_ref.size > fact_roles.size # Too many roles - next if role_sequence.all_role_ref.detect{|rsr| ft = rsr.role.fact_type; ft != fact_type } + next if role_sequence.all_role_ref.detect do |rsr| + if (of = rsr.role.fact_type) != fact_type + case of.all_role.size + when 1 # A unary FT must be played by the objectification of this fact type + next rsr.role.concept != fact_type.entity_type + when 2 # A binary FT must have the objectification of this FT as the other player + other_role = (of.all_role-[rsr.role])[0] + next other_role.concept != fact_type.entity_type + else + next true # A role in a ternary (or higher) cannot be usd in our identifier + end + end + rsr.role.fact_type != fact_type + end # This role sequence is a candidate pc = role_sequence.all_presence_constraint.detect{|c| c.max_frequency == 1 && c.is_preferred_identifier } @@ -241,13 +278,13 @@ } end # An array of self followed by all supertypes in order: def supertypes_transitive - ([self] + all_type_inheritance_by_subtype.map{|ti| - # debug ti.class.roles.verbalise; exit - ti.supertype.supertypes_transitive - }).flatten.uniq + ([self] + all_type_inheritance_by_subtype.map{|ti| + # debug ti.class.roles.verbalise; exit + ti.supertype.supertypes_transitive + }).flatten.uniq end # A subtype does not have a identifying_supertype if it defines its own identifier def identifying_supertype debug "Looking for identifying_supertype of #{name}"