lib/activefacts/generate/ordered.rb in activefacts-0.8.9 vs lib/activefacts/generate/ordered.rb in activefacts-0.8.10
- old
+ new
@@ -30,11 +30,11 @@
def generate(out = $>)
@out = out
vocabulary_start(@vocabulary)
build_indices
- @concept_types_dumped = {}
+ @object_types_dumped = {}
@fact_types_dumped = {}
units_dump()
value_types_dump()
entity_types_dump()
fact_types_dump()
@@ -65,39 +65,50 @@
def units_dump
done_banner = false
units = @vocabulary.all_unit.to_a.sort_by{|u| u.name.gsub(/ /,'')}
while units.size > 0
- if !done_banner
- done_banner = true
- units_banner
- end
i = 0
while i < units.size
unit = units[i]
i += 1
+
# Skip this one if the precursors haven't yet been dumped:
next if unit.all_derivation_as_derived_unit.detect{|d| units.include?(d.base_unit) }
- unit_dump(unit)
+ # Even if we skip, we're done with this unit
units.delete(unit)
i -= 1
+
+ # Skip value-type derived units
+ next if unit.name =~ /\^/
+
+ # Don't dump fundamental units which have normal derived units, they are implied:
+ next if unit.is_fundamental &&
+ unit.all_derivation_as_base_unit.detect{|d| d.derived_unit.name !~ /\^/}
+
+ if !done_banner
+ done_banner = true
+ units_banner
+ end
+ unit_dump(unit)
end
end
+ units_end if done_banner
end
def value_types_dump
done_banner = false
@value_type_dumped = {}
- @vocabulary.all_concept.sort_by{|o| o.name.gsub(/ /,'')}.each{|o|
+ @vocabulary.all_object_type.sort_by{|o| o.name.gsub(/ /,'')}.each{|o|
next unless o.is_a?(ActiveFacts::Metamodel::ValueType)
value_type_banner unless done_banner
done_banner = true
value_type_chain_dump(o)
- @concept_types_dumped[o] = true
+ @object_types_dumped[o] = true
}
value_type_end if done_banner
end
# Ensure that supertype gets dumped first
@@ -114,19 +125,19 @@
def entity_types_dump
# Build hash tables of precursors and followers to use:
@precursors, @followers = *build_entity_dependencies
done_banner = false
- sorted = @vocabulary.all_concept.select{|o|
+ sorted = @vocabulary.all_object_type.select{|o|
o.is_a?(ActiveFacts::Metamodel::EntityType) # and !o.fact_type
}.sort_by{|o| o.name.gsub(/ /,'')}
panic = nil
while true do
count_this_pass = 0
skipped_this_pass = 0
sorted.each{|o|
- next if @concept_types_dumped[o] # Already done
+ next if @object_types_dumped[o] # Already done
# Can we do this yet?
if (o != panic and # We don't *have* to do it (panic mode)
(p = @precursors[o]) and # There might be...
p.size > 0) # precursors - still blocked
@@ -158,24 +169,24 @@
# Check that we made progress if there's any to make:
if count_this_pass == 0 && skipped_this_pass > 0
if panic # We were already panicing... what to do now?
# This won't happen again unless the above code is changed to decide it can't dump "panic".
raise "Unresolvable cycle of forward references: " +
- (bad = sorted.select{|o| EntityType === o && !@concept_types_dumped[o]}).map{|o| o.name }.inspect +
+ (bad = sorted.select{|o| EntityType === o && !@object_types_dumped[o]}).map{|o| o.name }.inspect +
":\n\t" + bad.map{|o|
o.name +
": " +
@precursors[o].map{|p| p.name}.uniq.inspect
} * "\n\t" + "\n"
else
# Find the object that has the most followers and no fwd-ref'd supertypes:
# This selection might be better if we allow PI roles to be fwd-ref'd...
panic = sorted.
- select{|o| !@concept_types_dumped[o] }.
+ select{|o| !@object_types_dumped[o] }.
sort_by{|o|
f = @followers[o] || [];
- o.supertypes.detect{|s| !@concept_types_dumped[s] } ? 0 : -f.size
+ o.supertypes.detect{|s| !@object_types_dumped[s] } ? 0 : -f.size
}[0]
# debug "Panic mode, selected #{panic.name} next"
end
end
@@ -183,11 +194,11 @@
end
end
def entity_type_dump(o)
- @concept_types_dumped[o] = true
+ @object_types_dumped[o] = true
pi = o.preferred_identifier
supers = o.supertypes
if (supers.size > 0)
# Ignore identification by a supertype:
@@ -208,11 +219,10 @@
# We need to get the adjectives for the roles from the identifying fact's preferred readings:
identifying_facts = ([o.fact_type]+identifying_role_refs.map{|rr| rr.role.fact_type }).compact.uniq
identification = identified_by_roles_and_facts(o, identifying_role_refs, identifying_facts)
- #identifying_facts.each{|f| @fact_types_dumped[f] = true }
identification
end
def describe_fact_type(fact_type, highlight = nil)
@@ -220,45 +230,45 @@
describe_roles(fact_type.all_role, highlight)
end
def describe_roles(roles, highlight = nil)
"("+
- roles.map{|role| role.concept.name + (role == highlight ? "*" : "")}*", "+
+ roles.map{|role| role.object_type.name + (role == highlight ? "*" : "")}*", "+
")"
end
def describe_role_sequence(role_sequence)
"("+
- role_sequence.all_role_ref.map{|role_ref| role_ref.role.concept.name }*", "+
+ role_sequence.all_role_ref.map{|role_ref| role_ref.role.object_type.name }*", "+
")"
end
# 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_concept.inject([{},{}]) { |a, o|
+ @vocabulary.all_object_type.inject([{},{}]) { |a, o|
if o.is_a?(ActiveFacts::Metamodel::EntityType)
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
+ player = role.object_type
# REVISIT: If we decide to emit value types on demand, need to remove this:
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
if o.fact_type
o.fact_type.all_role.each do |role|
- next unless role.concept.is_a?(ActiveFacts::Metamodel::EntityType)
- (precursor[o] ||= []) << role.concept
- (follower[role.concept] ||= []) << o
+ next unless role.object_type.is_a?(ActiveFacts::Metamodel::EntityType)
+ (precursor[o] ||= []) << role.object_type
+ (follower[role.object_type] ||= []) << o
end
end
# Supertypes are precursors too:
subtyping = o.all_type_inheritance_as_supertype
@@ -287,13 +297,14 @@
progress = false
roles.map(&:fact_type).uniq.select{|fact_type|
# The fact type hasn't already been dumped but all its role players have
!@fact_types_dumped[fact_type] &&
!fact_type.is_a?(ActiveFacts::Metamodel::ImplicitFactType) &&
- !fact_type.all_role.detect{|r| !@concept_types_dumped[r.concept] } &&
- !fact_type.entity_type
-# !(fact_type.entity_type && (p = @precursors[fact_type.entity_type]) && p.size > 0)
+ !fact_type.all_role.detect{|r| !@object_types_dumped[r.object_type] } &&
+ !fact_type.entity_type &&
+ derivation_precursors_complete(fact_type)
+ # REVISIT: A derived fact type must not be dumped before its joined fact types have
}.sort_by{|fact_type|
fact_type_key(fact_type)
}.each{|fact_type|
fact_type_dump_with_dependents(fact_type)
# Objectified Fact Types may release additional fact types
@@ -301,16 +312,26 @@
progress = true
}
end while progress
end
+ def derivation_precursors_complete(fact_type)
+ pr = fact_type.preferred_reading
+ return true unless jr = pr.role_sequence.all_role_ref.to_a[0].join_role
+ join = jr.join_node.join
+ return false if join.all_join_step.detect{|js| !@fact_types_dumped[js.fact_type] }
+ return false if join.all_join_node.detect{|jn| !@object_types_dumped[jn.object_type] }
+ true
+ end
+
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]
- f.is_a?(ActiveFacts::Metamodel::TypeInheritance) ||
- (pcs && pcs.size > 0 && !pcs.detect{|c| !@constraints_used[c] })
+ return true if f.is_a?(ActiveFacts::Metamodel::TypeInheritance)
+ return false if f.entity_type && !@object_types_dumped[f.entity_type]
+ 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.
def fact_type_dump_with_dependents(fact_type)
@@ -339,11 +360,11 @@
fact_type_dump(fact_type, name)
# REVISIT: Go through the residual constraints and re-process appropriate readings to show them
@fact_types_dumped[fact_type] = true
- @concept_types_dumped[fact_type.entity_type] = true if fact_type.entity_type
+ @object_types_dumped[fact_type.entity_type] = true if fact_type.entity_type
end
# Dump fact types.
def fact_types_dump
# REVISIT: Uniqueness on the LHS of a binary can be coded using "distinct"
@@ -358,11 +379,11 @@
fact_type = fact_collection[fact_id] and
!fact_type.is_a?(ActiveFacts::Metamodel::TypeInheritance) and
!fact_type.is_a?(ActiveFacts::Metamodel::ImplicitFactType) and
!@fact_types_dumped[fact_type] and
!skip_fact_type(fact_type) and
- !fact_type.all_role.detect{|r| r.concept.is_a?(ActiveFacts::Metamodel::EntityType) }
+ !fact_type.all_role.detect{|r| r.object_type.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]
@@ -378,11 +399,11 @@
!fact_type.is_a?(ActiveFacts::Metamodel::ImplicitFactType)
}.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}*", "})"
+ # debug "Not dumped #{fact_type.verbalise}(#{fact_type.all_role.map{|r| r.object_type.name}*", "})"
fact_type_banner unless done_banner
done_banner = true
fact_type_dump_with_dependents(fact_type)
}
@@ -410,32 +431,32 @@
role_names =
if (pr = fact_type.preferred_reading)
pr.role_sequence.
all_role_ref.
sort_by{|role_ref| role_ref.ordinal}.
- map{|role_ref| [ role_ref.leading_adjective, role_ref.role.concept.name, role_ref.trailing_adjective ].compact*"-" } +
+ map{|role_ref| [ role_ref.leading_adjective, role_ref.role.object_type.name, role_ref.trailing_adjective ].compact*"-" } +
[pr.text]
else
- fact_type.all_role.map{|role| role.concept.name }
+ fact_type.all_role.map{|role| role.object_type.name }
end
(fact_type.entity_type ? [fact_type.entity_type.name] : [""]) + role_names
end
def role_ref_key(role_ref)
- [ role_ref.leading_adjective, role_ref.role.concept.name, role_ref.trailing_adjective ].compact*"-" +
+ [ role_ref.leading_adjective, role_ref.role.object_type.name, role_ref.trailing_adjective ].compact*"-" +
" in " +
role_ref.role.fact_type.preferred_reading.expand
end
def constraint_sort_key(c)
case c
when ActiveFacts::Metamodel::RingConstraint
[ 1,
c.ring_type,
- c.role.concept.name,
- c.other_role.concept.name,
+ c.role.object_type.name,
+ c.other_role.object_type.name,
c.name||""
]
when ActiveFacts::Metamodel::SetExclusionConstraint
[ 2+(c.is_mandatory ? 0 : 1),
c.all_set_comparison_roles.map{|scrs|
@@ -497,11 +518,11 @@
constraint_banner unless heading
heading = true
# Skip presence constraints on value types:
# next if ActiveFacts::PresenceConstraint === c &&
- # ActiveFacts::ValueType === c.concept
+ # ActiveFacts::ValueType === c.object_type
constraint_dump(c)
end
constraint_end if heading
end
@@ -512,9 +533,12 @@
def vocabulary_end
debug "Should override vocabulary_end"
end
def units_banner
+ end
+
+ def units_end
end
def unit_dump unit
end