lib/activefacts/generate/ordered.rb in activefacts-0.7.2 vs lib/activefacts/generate/ordered.rb in activefacts-0.7.3
- old
+ new
@@ -8,12 +8,10 @@
module ActiveFacts
module Generate #:nodoc:
class OrderedDumper #:nodoc:
# Base class for generators of object-oriented class libraries for an ActiveFacts vocabulary.
- include Metamodel
-
def initialize(vocabulary, *options)
@vocabulary = vocabulary
@vocabulary = @vocabulary.Vocabulary.values[0] if ActiveFacts::API::Constellation === @vocabulary
options.each{|option| set_option(option) }
end
@@ -47,48 +45,59 @@
@presence_constraints_by_fact = Hash.new{ |h, k| h[k] = [] }
@ring_constraints_by_fact = Hash.new{ |h, k| h[k] = [] }
@vocabulary.all_constraint.each { |c|
case c
- when PresenceConstraint
+ when ActiveFacts::Metamodel::PresenceConstraint
fact_types = c.role_sequence.all_role_ref.map{|rr| rr.role.fact_type}.uniq # All fact types spanned by this constraint
if fact_types.size == 1 # There's only one, save it:
# debug "Single-fact constraint on #{fact_types[0].fact_type_id}: #{c.name}"
(@presence_constraints_by_fact[fact_types[0]] ||= []) << c
end
- when RingConstraint
+ when ActiveFacts::Metamodel::RingConstraint
(@ring_constraints_by_fact[c.role.fact_type] ||= []) << c
else
# debug "Found unhandled constraint #{c.class} #{c.name}"
end
}
@constraints_used = {}
end
def value_types_dump
done_banner = false
+ @value_type_dumped = {}
@vocabulary.all_feature.sort_by{|o| o.name}.each{|o|
- next unless ValueType === o
+ next unless o.is_a?(ActiveFacts::Metamodel::ValueType)
value_type_banner unless done_banner
done_banner = true
- value_type_dump(o)
+ value_type_chain_dump(o)
@concept_types_dumped[o] = true
}
value_type_end if done_banner
end
+ # Ensure that supertype gets dumped first
+ def value_type_chain_dump(o)
+ return if @value_type_dumped[o]
+ value_type_chain_dump(o.supertype) if (o.supertype && !@value_type_dumped[o.supertype])
+ value_type_dump(o)
+ @value_type_dumped[o] = true
+ end
+
# Try to dump entity types in order of name, but we need
# to dump ETs before they're referenced in preferred ids
# if possible (it's not always, there may be loops!)
def entity_types_dump
# Build hash tables of precursors and followers to use:
precursors, followers = *build_entity_dependencies
done_banner = false
- sorted = @vocabulary.all_feature.select{|o| EntityType === o and !o.fact_type }.sort_by{|o| o.name}
+ sorted = @vocabulary.all_feature.select{|o|
+ o.is_a?(ActiveFacts::Metamodel::EntityType) and !o.fact_type
+ }.sort_by{|o| o.name}
panic = nil
while true do
count_this_pass = 0
skipped_this_pass = 0
sorted.each{|o|
@@ -152,11 +161,11 @@
pi = o.preferred_identifier
supers = o.supertypes
if (supers.size > 0)
# Ignore identification by a supertype:
- pi = nil if pi && pi.role_sequence.all_role_ref.detect{|rr| rr.role.fact_type.is_a?(TypeInheritance) }
+ pi = nil if pi && pi.role_sequence.all_role_ref.detect{|rr| rr.role.fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance) }
subtype_dump(o, supers, pi)
else
non_subtype_dump(o, pi)
end
@constraints_used[pi] = true
@@ -220,11 +229,11 @@
# REVISIT: With a ternary, doing this on other than the last role can be ambiguous,
# in case both the 2nd and 3rd roles have frequencies. Think some more!
constraint = fact_constraints.find{|c| # Find a UC that spans all other Roles
# internal uniqueness constraints span all roles but one, the residual:
- PresenceConstraint === c &&
+ c.is_a?(ActiveFacts::Metamodel::PresenceConstraint) &&
!@constraints_used[c] && # Already verbalised
roles-c.role_sequence.all_role_ref.map(&:role) == [role]
}
# Index the frequency implied by the constraint under the role position in the reading
if constraint # Mark this constraint as "verbalised" so we don't do it again:
@@ -269,20 +278,20 @@
# This returns an array of two hash tables each keyed by an EntityType.
# The values of each hash entry are the precursors and followers (respectively) of that entity.
def build_entity_dependencies
@vocabulary.all_feature.inject([{},{}]) { |a, o|
- if EntityType === o && !o.fact_type
+ if o.is_a?(ActiveFacts::Metamodel::EntityType) && !o.fact_type
precursor = a[0]
follower = a[1]
blocked = false
pi = o.preferred_identifier
if pi
pi.role_sequence.all_role_ref.each{|rr|
role = rr.role
player = role.concept
- next unless EntityType === player
+ next unless player.is_a?(ActiveFacts::Metamodel::EntityType)
# player is a precursor of o
(precursor[o] ||= []) << player if (player != o)
(follower[player] ||= []) << o if (player != o)
}
end
@@ -322,11 +331,11 @@
def skip_fact_type(f)
# REVISIT: There might be constraints we have to merge into the nested entity or subtype.
# These will come up as un-handled constraints:
pcs = @presence_constraints_by_fact[f]
- TypeInheritance === f ||
+ f.is_a?(ActiveFacts::Metamodel::TypeInheritance) ||
(pcs && pcs.size > 0 && !pcs.detect{|c| !@constraints_used[c] })
end
# Dump one fact type.
# Include as many as possible internal constraints in the fact type readings.
@@ -393,14 +402,14 @@
done_banner = false
fact_collection = @vocabulary.constellation.FactType
fact_collection.keys.select{|fact_id|
fact_type = fact_collection[fact_id] and
- !(TypeInheritance === fact_type) and
+ !fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance) and
!@fact_types_dumped[fact_type] and
!skip_fact_type(fact_type) and
- !fact_type.all_role.detect{|r| r.concept.is_a?(EntityType) }
+ !fact_type.all_role.detect{|r| r.concept.is_a?(ActiveFacts::Metamodel::EntityType) }
}.sort_by{|fact_id|
fact_type = fact_collection[fact_id]
fact_type_key(fact_type)
}.each{|fact_id|
fact_type = fact_collection[fact_id]
@@ -410,11 +419,11 @@
fact_type_dump_with_dependents(fact_type)
}
# REVISIT: Find out why some fact types are missed during entity dumping:
@vocabulary.constellation.FactType.values.select{|fact_type|
- !(TypeInheritance === fact_type)
+ !fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance)
}.sort_by{|fact_type|
fact_type_key(fact_type)
}.each{|fact_type|
next if @fact_types_dumped[fact_type]
# debug "Not dumped #{fact_type.verbalise}(#{fact_type.all_role.map{|r| r.concept.name}*", "})"
@@ -440,34 +449,34 @@
}
end
def constraint_sort_key(c)
case c
- when RingConstraint
+ when ActiveFacts::Metamodel::RingConstraint
[1, c.ring_type, c.role.concept.name, c.other_role.concept.name, c.name||""]
- when SetComparisonConstraint
+ when ActiveFacts::Metamodel::SetComparisonConstraint
[2, c.all_set_comparison_roles.map{|scrs| scrs.role_sequence.all_role_ref.map{|rr| role_ref_key(rr)}}, c.name||""]
- when SubsetConstraint
+ when ActiveFacts::Metamodel::SubsetConstraint
[3, [c.superset_role_sequence, c.subset_role_sequence].map{|rs| rs.all_role_ref.map{|rr| role_ref_key(rr)}}, c.name||""]
- when PresenceConstraint
+ when ActiveFacts::Metamodel::PresenceConstraint
[4, c.role_sequence.all_role_ref.map{|rr| role_ref_key(rr)}, c.name||""]
end
end
def constraints_dump(except = {})
heading = false
@vocabulary.all_constraint.reject{|c| except[c]}.sort_by{ |c| constraint_sort_key(c) }.each do|c|
# Skip some PresenceConstraints:
- if PresenceConstraint === c
+ if c.is_a?(ActiveFacts::Metamodel::PresenceConstraint)
# Skip uniqueness constraints that cover all roles of a fact type, they're implicit
fact_types = c.role_sequence.all_role_ref.map{|rr| rr.role.fact_type}.uniq
next if fact_types.size == 1 &&
c.max_frequency == 1 && # Uniqueness
fact_types[0].all_role.size == c.role_sequence.all_role_ref.size
# Skip internal PresenceConstraints over TypeInheritances:
next if c.role_sequence.all_role_ref.size == 1 &&
- TypeInheritance === fact_types[0]
+ fact_types[0].is_a?(ActiveFacts::Metamodel::TypeInheritance)
end
constraint_banner unless heading
heading = true