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