#
# ActiveFacts Generators.
#
# Generate a glossary in HTML
#
# Copyright (c) 2009 Clifford Heath. Read the LICENSE file.
#
require 'activefacts/api'
module ActiveFacts
module Generate #:nodoc:
class HTML #:nodoc:
class GLOSSARY #:nodoc:
# Base class for generators of object-oriented class libraries for an ActiveFacts vocabulary.
def initialize(vocabulary, *options)
@vocabulary = vocabulary
@vocabulary = @vocabulary.Vocabulary.values[0] if ActiveFacts::API::Constellation === @vocabulary
options.each{|option| set_option(option) }
end
def set_option(option)
end
def puts(*a)
@out.puts *a
end
def print(*a)
@out.print *a
end
def generate(out = $>)
@out = out
vocabulary_start
object_types_dump()
vocabulary_end
end
def vocabulary_start
# puts ""
File.open(File.dirname(__FILE__)+"/../../../../css/orm2.css") do |f|
puts ""
end
puts %Q{
}.gsub(/^\s+/, '')
end
def vocabulary_end
puts %Q{
}.gsub(/^\s+/, '')
end
def object_types_dump
all_object_type =
@vocabulary.
all_object_type.
sort_by{|o| o.name.gsub(/ /,'').downcase}
# Put out a table of contents first:
puts '
'
puts ''
all_object_type.
reject do |o|
o.name == '_ImplicitBooleanValueType' or
o.kind_of?(ActiveFacts::Metamodel::ValueType) && o.all_role.size == 0 or
o.kind_of?(ActiveFacts::Metamodel::TypeInheritance)
end.
each do |o|
puts "
#{termref(o.name)}
"
end
puts ''
puts '
'
puts ' '
puts ' '
puts ' '
puts '
'
puts '
'
puts '
'
puts "
#{@vocabulary.name}
"
puts '
'
all_object_type.
each do |o|
case o
when ActiveFacts::Metamodel::TypeInheritance
nil
when ActiveFacts::Metamodel::ValueType
value_type_dump(o)
else
if o.fact_type
objectified_fact_type_dump(o)
else
entity_type_dump(o)
end
end
end
puts '
'
puts '
'
end
def element(text, attrs, tag = 'span')
"<#{tag}#{attrs.empty? ? '' : attrs.map{|k,v| " #{k}='#{v}'"}*''}>#{text}#{tag}>"
end
def span(text, klass = nil)
element(text, klass ? {:class => klass} : {})
end
def div(text, klass = nil)
element(text, klass ? {:class => klass} : {}, 'div')
end
def h1(text, klass = nil)
element(text, klass ? {:class => klass} : {}, 'h1')
end
def dl(text, klass = nil)
element(text, klass ? {:class => klass} : {}, 'dl')
end
# A definition of a term
def termdef(name)
element(name, {:name => name, :class => 'object_type'}, 'a')
end
# A reference to a defined term (excluding role adjectives)
def termref(name, role_name = nil)
role_name ||= name
element(role_name, {:href=>'#'+name, :class=>:object_type}, 'a')
end
# Text that should appear as part of a term (including role adjectives)
def term(name)
element(name, :class=>:object_type)
end
def value_type_dump(o)
return if o.all_role.size == 0 or # Skip value types that are only used as supertypes
o.name == '_ImplicitBooleanValueType'
puts "
" +
"#{termdef(o.name)} " +
(if o.supertype
span('is written as ', :keyword) + termref(o.supertype.name)
else
" (a fundamental data type)"
end) +
"
"
# REVISIT: Handle separate identification
puts "
"
puts fact_type_with_constraints(o.fact_type)
o.fact_type.all_role_in_order.each do |r|
n = r.object_type.name
puts div("#{termref(o.name)} involves #{span('one', 'keyword')} #{termref(r.role_name || n, n)}", "glossary-facttype")
end
relevant_facts_and_constraints(o)
puts "
"
end
def entity_type_dump(o)
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?(ActiveFacts::Metamodel::TypeInheritance) }
end
puts "
"
end
def entities(o)
return if o.preferred_identifier.role_sequence.all_role_ref.size > 1 # REVISIT: Composite identification
o.all_instance.each do |i|
v = i.value
ii = i # The identifying instance
until v
pi = ii.object_type.preferred_identifier # ii is an Entity Type
break if pi.role_sequence.all_role_ref.size > 1 # REVISIT: Composite identification
identifying_fact_type = pi.role_sequence.all_role_ref.single.role.fact_type
# Find the role played by this instance through which it is identified:
irv = i.all_role_value.detect{|rv| rv.fact.fact_type == identifying_fact_type }
# Get the other RoleValue in what must be a binary fact type:
orv = irv.fact.all_role_value.detect{|rv| rv != irv}
ii = orv.instance
v = ii.value # Does this instance have a value? If so, we're done.
end
next unless v
puts div(
(i.population.name.empty? ? '' : i.population.name+': ') +
termref(o.name) + ' ' +
div(
# v.is_literal_string ? v.literal.inspect : v.literal,
v.literal.inspect,
'value'),
'glossary-example'
)
end
end
end
end
end
end
ActiveFacts::Registry.generator('html/glossary', ActiveFacts::Generate::HTML::GLOSSARY)