@mainClass "ch::uzh::ifi::rerg::e2html::E2HTML"
@mainOperation "main"
package ch::uzh::ifi::rerg::e2html;
require kermeta
require "Ecore.kmt"
require "HTML.kmt"
using kermeta::standard
using kermeta::utils
using kermeta::persistence
using kermeta::io
using ecore
using html
class E2HTML
{
operation main(inputURI: String, outputURI: String): Void is do
var pkgs: OrderedSet init loadModel(inputURI)
var doc: HTML init createDoc(pkgs)
saveDocText(doc, outputURI)
end
attribute modelURI: String
operation loadModel(mmURI: String): OrderedSet is do
var rep : EMFRepository init EMFRepository.new
var res : EMFResource
res ?= rep.getResource(mmURI)
result := OrderedSet.new
res.select{e | e.isKindOf(EPackage)}.each{p | result.add(p.asType(EPackage))}
modelURI := mmURI
end
operation saveDocModel(doc: HTML, uri: String): Void is do
var rep : EMFRepository init EMFRepository.new
var res : EMFResource
res ?= rep.createResource(uri, "http://www.ifi.uzh.ch/rerg/html")
res.add(doc)
res.save()
end
operation saveDocText(doc: HTML, uri: String): Void is do
var file : FileIO init FileIO.new
file.writeTextFile(uri,doc.toHTML())
end
reference ctx: HTMLElement
operation createDoc(pkgs: OrderedSet): HTML is do
result := HTML.new
result.title := "Metamodel Documentation"
ctx := result
pkgs.each{p | visitPackage(p)}
end
operation visitPackage(pkg: EPackage): Void is do
ctx.createH1(getPackageID(pkg)).createText("EPackage: " + pkg.name)
insertDoc(pkg,ctx)
pkg.eClassifiers.select{c | c.isInstanceOf(EClass)}.each{c | visitClass(c.asType(EClass))}
pkg.eClassifiers.select{c | c.isInstanceOf(EEnum)}.each{c | visitEnum(c.asType(EEnum))}
pkg.eClassifiers.select{c | c.isInstanceOf(EDataType) and (not (c.isInstanceOf(EEnum)))}.each{c | visitPrimitiveType(c.asType(EDataType))}
pkg.eSubpackages.each{p | visitPackage(p)}
end
operation visitClass(cl: EClass): Void is do
var h2: H2 init ctx.createH2(getClassifierID(cl))
h2.createText("EClass: ")
if cl.~abstract
then
h2.createText(cl.name).makeEM()
else
h2.createText(cl.name)
end
insertDoc(cl, ctx)
if not cl.eSuperTypes.isEmpty
then
ctx.createH3().createText("Inherits from")
var ul: UL init ctx.createUL()
cl.eSuperTypes.each{scl | ul.createLI().createText(scl.name).makeA("#"+getClassifierID(scl))}
end
if not cl.eStructuralFeatures.isEmpty
then
ctx.createH3().createText("Structural Features")
var oldCtx: HTMLElement init ctx
ctx := ctx.createTABLE()
cl.eStructuralFeatures.each{feat | visitTypedElement(feat)}
ctx := oldCtx
end
if not cl.eOperations.isEmpty
then
ctx.createH3().createText("Operations")
var oldCtx: HTMLElement init ctx
ctx := ctx.createTABLE()
cl.eOperations.each{op | visitOperation(op)}
ctx := oldCtx
end
end
operation visitTypedElement(te: ETypedElement): Void is do
var oldCtx: HTMLElement init ctx
ctx := ctx.createTR()
var typeTD: TD init ctx.createTD()
if isTypeInDocument(te.eType)
then
typeTD.createText(te.eType.name).makeA("#" + getClassifierID(te.eType))
else
typeTD.createText("?")
end
ctx.createTD().createText(getMultiplicity(te))
ctx.createTD().createText(te.name)
insertDoc(te,ctx.createTD())
ctx := oldCtx
end
operation visitOperation(op: EOperation): Void is do
var oldCtx: HTMLElement init ctx
ctx := ctx.createTR()
var typeTD: TD init ctx.createTD()
if isTypeInDocument(op.eType)
then
typeTD.createText(op.eType.name).makeA("#" + getClassifierID(op.eType))
else
typeTD.createText("?")
end
var nameTD: TD init ctx.createTD()
nameTD.createText(op.name)
insertDoc(op,nameTD)
var paramTD: TD init ctx.createTD()
if not op.eParameters.isEmpty
then
ctx := paramTD.createTABLE()
op.eParameters.each{p | visitTypedElement(p)}
else
paramTD.createText("-")
end
ctx := oldCtx
end
operation isTypeInDocument(type: EClassifier): Boolean is do
result := false
if not type.isVoid
then
if not type.containingResource.isVoid
then
if type.containingResource.uri == modelURI
then
result := true
end
end
end
end
operation visitEnum(en: EEnum): Void is do
ctx.createH2(getClassifierID(en)).createText("EEnum: " + en.name)
insertDoc(en,ctx)
var oldCtx: HTMLElement init ctx
ctx := ctx.createUL()
en.eLiterals.each{l | visitEnumLiteral(l)}
ctx := oldCtx
end
operation visitEnumLiteral(el: EEnumLiteral): Void is do
var li: LI init ctx.createLI()
li.createText(el.~value.toString + ": ")
li.createText(el.name).makeEM()
insertDoc(el,li)
end
operation visitPrimitiveType(pt: EDataType): Void is do
ctx.createH2(getClassifierID(pt)).createText("EDataType: " + pt.name)
insertDoc(pt,ctx)
if not pt.instanceTypeName.isVoid
then
var p: P init ctx.createP()
p.createText("Mapped to: ")
p.createText(pt.instanceTypeName).makeEM()
end
end
operation getClassifierID(cl: EClassifier): String is do
result := getPackageID(cl.ePackage) + "." + cl.name
end
operation getPackageID(pkg: EPackage): String is do
if pkg.eSuperPackage.isVoid
then
result := pkg.name
else
result := getPackageID(pkg.eSuperPackage) + "." + pkg.name
end
end
operation getMultiplicity(feat: ETypedElement): String is do
var sb: StringBuffer init StringBuffer.new
sb.append("[")
sb.append(feat.lowerBound.toString)
sb.append(",")
if feat.upperBound == -1
then
sb.append("*")
else
sb.append(feat.upperBound.toString)
end
sb.append("]")
result := sb.toString
end
operation insertDoc(elem: EModelElement, par: HTMLElement): Void is do
var an: EAnnotation init elem.getEAnnotation("http://www.eclipse.org/emf/2002/GenModel")
if not an.isVoid
then
var det: EStringToStringMapEntry init an.details.detect { a | "documentation".equals(a.key)}
if not det.isVoid
then
par.createPRE().createText(det.~value)
end
end
end
}