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}"