@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 }