"""Module Documentation here
"""
#=========================================================================================
# Licence, Reference and Credits
#=========================================================================================
__copyright__ = "Copyright (C) CCPN project (http://www.ccpn.ac.uk) 2014 - 2017"
__credits__ = ("Wayne Boucher, Ed Brooksbank, Rasmus H Fogh, Luca Mureddu, Timothy J Ragan & Geerten W Vuister")
__licence__ = ("CCPN licence. See http://www.ccpn.ac.uk/v3-software/downloads/license",
"or ccpnmodel.ccpncore.memops.Credits.CcpnLicense for licence text")
__reference__ = ("For publications, please use reference from http://www.ccpn.ac.uk/v3-software/downloads/license",
"or ccpnmodel.ccpncore.memops.Credits.CcpNmrReference")
#=========================================================================================
# Last code modification
#=========================================================================================
__modifiedBy__ = "$modifiedBy: CCPN $"
__dateModified__ = "$dateModified: 2017-07-07 16:33:24 +0100 (Fri, July 07, 2017) $"
__version__ = "$Revision: 3.0.0 $"
#=========================================================================================
# Created
#=========================================================================================
__author__ = "$Author: CCPN $"
__date__ = "$Date: 2017-04-07 10:28:48 +0000 (Fri, April 07, 2017) $"
#=========================================================================================
# Start of code
#=========================================================================================
"""
======================COPYRIGHT/LICENSE START==========================
ApiDocGen.py: Code generation for CCPN framework
Copyright (C) 2007 Wayne Boucher (CCPN Project)
=======================================================================
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
A copy of this license can be found in ../license/GPL.license
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
======================COPYRIGHT/LICENSE END============================
for further information, please contact :
- CCPN website (http://www.ccpn.ac.uk/)
- email: ccpn@bioc.cam.ac.uk
=======================================================================
If you are using this software for academic purposes, we suggest
quoting the following references:
===========================REFERENCE START=============================
R. Fogh, J. Ionides, E. Ulrich, W. Boucher, W. Vranken, J.P. Linge, M.
Habeck, W. Rieping, T.N. Bhat, J. Westbrook, K. Henrick, G. Gilliland,
H. Berman, J. Thornton, M. Nilges, J. Markley and E. Laue (2002). The
CCPN project: An interim report on a data model for the NMR community
(Progress report). Nature Struct. Biol. 9, 416-418.
Rasmus H. Fogh, Wayne Boucher, Wim F. Vranken, Anne
Pajon, Tim J. Stevens, T.N. Bhat, John Westbrook, John M.C. Ionides and
Ernest D. Laue (2005). A framework for scientific data modeling and automated
software development. Bioinformatics 21, 1678-1684.
===========================REFERENCE END===============================
"""
import os
import string
from ccpnmodel.ccpncore.memops.metamodel import MetaModel
from ccpnmodel.ccpncore.memops.metamodel.ModelTraverse import ModelTraverse
from ccpnmodel.ccpncore.memops.metamodel import OpTypes
from ccpnmodel.ccpncore.memops.metamodel import Util as metaUtil
from ccpnmodel.ccpncore.memops.metamodel import Constants as metaConstants
from ccpnmodel.ccpncore.memops.license import data as licenseData
from ccpn.util import Path as Path
from ccpnmodel.ccpncore.memops.license import headers
from ccpnmodel.ccpncore.memops.metamodel import TextWriter
from ccpnmodel.ccpncore.memops.scripts.docgen.Documentation import Documentation
infinity = metaConstants.infinity
MemopsError = MetaModel.MemopsError
mandatoryAttributes = ('apiName', 'baseDirName', 'fileSuffix', 'scriptName')
attrOpTypes = ['get', 'set', 'sorted', 'add', 'remove', 'findFirst', 'findAll']
classOpTypes = ['fullDelete', 'fullUnDelete', 'checkValid', 'checkAllValid', 'getByKey',
'getFullKey', 'getLocalKey', 'getAttr', 'setAttr', 'clone']
newOpTypes = ['new']
otherOpTypes = ['otherQuery', 'otherModify', 'otherCreate', 'otherDelete',
'other']
ignoreOpTypes = ['init', 'checkDelete', 'singleDelete', 'singleUnDelete']
# check that not missing something and that do not have any extra
usedOpTypes = list(attrOpTypes + classOpTypes + newOpTypes + otherOpTypes + ignoreOpTypes)
usedOpTypes.sort()
allOpTypes = list(OpTypes.operationData.keys())
allOpTypes.sort()
if usedOpTypes != allOpTypes:
raise Exception('allOpTypes = %s, usedOpTypes = %s' % (allOpTypes, usedOpTypes))
# pkgGroup* stuff is for diagrams
pkgGroupData = {
'core':{'htmlClass':'',
'homeTitle'
:'Core packages (CCPN)'
},
'nmr':{'htmlClass':'nmr',
'homeTitle':'NMR and related packages (CCPN)'
},
'pp':{'htmlClass':'ppdm',
'homeTitle':'Protein Production packages (EBI/MSD)'
}
}
pkgGroupOrder = ('pp', 'core', 'nmr')
# Requires other writers also to be implemented in subclass
[docs]class ApiDocGen(Documentation, ModelTraverse):
topApiPrefix = 'api'
classMapPrefix = 'classMap'
methodMapPrefix = 'methodMap'
indexPrefix = '_index'
###attrRoleDir = 'attributeMap'
attributeMapPrefix = 'attributeMap'
imageDir = metaConstants.imageDir
# docDir = metaConstants.docDir
apiFileDir = 'static'
# docSubDirs = ['api','doc']
# modelDiagramDir = 'doc'
diagImgDir = 'apidiagram'
diagFileExt = '_Diag.gif'
detailDiagExt = '-details'
helpPrefix = 'help'
licensePrefix = 'license'
draftDocString = """
DRAFT - backward compatibility of future versions not guaranteed.<br>
"""
###########################################################################
###########################################################################
def __init__(self):
settings = TextWriter.settings['html']
for (tag, val) in settings.items():
if not hasattr(self, tag):
setattr(self, tag, val)
for tag in mandatoryAttributes:
if not hasattr(self, tag):
raise MemopsError("ApiDocGen lacks mandatory %s attribute" % tag)
#self.codeDirName = uniIo.joinPath(genConstants.apiCodeDir, self.docDir)
self.codeDirName = metaConstants.apiCodeDir
# self.topDocDir = Path.joinPath(self.baseDirName, self.docDir)
self.modelDiagramDir = Path.joinPath(self.baseDirName, self.diagImgDir)
# self.baseDirName = Path.joinPath(self.baseDirName, self.docDir)
self.topDocDir = Path.joinPath(self.baseDirName, metaConstants.docDir)
self.topApiFile = '%s.%s' % (self.topApiPrefix, self.fileSuffix)
self.classMapFile = '%s.%s' % (self.classMapPrefix, self.fileSuffix)
self.methodMapFile = '%s.%s' % (self.methodMapPrefix, self.fileSuffix)
self.attributeMapFile = '%s.%s' % (self.attributeMapPrefix, self.fileSuffix)
self.indexFile = '%s.%s' % (self.indexPrefix, self.fileSuffix)
self.handCodeKey = self.typeCodeKey = self.modelFlavours['language']
self.impPackage = None
# init handling
#super(ApiDocGen, self).__init__()
Documentation.__init__(self)
ModelTraverse.__init__(self)
self.diagramOrderedPackages = self.getDiagramOrderedPackages()
# get dictionary of -to-one links and datatype use
self.valueTypeUse = valueTypeUse = {}
for pp in self.modelPortal.leafPackagesByImport():
for cc in self.modelPortal.classesByInheritance(pp):
# add one-way roles
for role in cc.roles:
if role.otherRole is None and not role.isImplicit:
# one-way link
valueType = role.valueType
ll = valueTypeUse.get(valueType)
if ll is None:
valueTypeUse[valueType] = [role]
else:
ll.append(role)
# add datatype use
for attr in cc.attributes:
if not attr.isImplicit:
valueType = attr.valueType
ll = valueTypeUse.get(valueType)
if ll is None:
valueTypeUse[valueType] = [attr]
else:
ll.append(attr)
for cc in self.modelPortal.dataObjTypesByInheritance(pp):
# add datatype use
for attr in cc.attributes:
if not attr.isImplicit:
valueType = attr.valueType
ll = valueTypeUse.get(valueType)
if ll is None:
valueTypeUse[valueType] = [attr]
else:
ll.append(attr)
# TBD: relies on separator being /
# self.baseDirNames = self.baseDirName.split('/')
###########################################################################
###########################################################################
###
### code overriding ModelTraverse
###
###########################################################################
###########################################################################
# overrides ModelTraverse
[docs] def processBranchPackage(self, package):
""" processing actions for branch package
"""
packageDirName = self.getObjDocDirName(package)
#print 'processBranchPackage', package.qualifiedName(), packageDirName
if package in self.modelPortal.twigPackages():
self.clearOutDir(packageDirName)
self.createDir(packageDirName)
if package.container:
directory = self.getObjDocDirName(package)
fileName = Path.joinPath(directory, self.indexPrefix)
else:
fileName = Path.joinPath(self.rootDirName, self.topDocDir, self.topApiPrefix)
self.impPackage = package.getElement(metaConstants.modellingPackageName).getElement(metaConstants.implementationPackageName)
self.openFile(fileName)
self.writeElementComment(package)
title = 'CCPN %s' % self.apiName
if package.container:
title += ' - %s' % self.getImportName(package)
(prev, foll) = self.getPrevNextPackages(package)
self.writeElementHeader(package, title, prev=prev, foll=foll)
if package.container:
self.writeBranchPackage(package)
else:
self.writeRootPackage(package)
self.writeObjectFooter(package)
self.closeFile()
# write class, attribute, method maps (only do once, for root package)
if not package.container:
# write class map
fileName = Path.joinPath(self.rootDirName, self.topDocDir, self.classMapPrefix)
self.openFile(fileName)
title = 'CCPN %s - Class Map' % self.apiName
self.writeElementHeader(package, title, special='Class Map')
self.writeClassMap(package)
self.closeFile()
# write attribute map
##self.writeAttrRoleMap(package)
fileName = Path.joinPath(self.rootDirName, self.topDocDir, self.attributeMapPrefix)
self.openFile(fileName)
title = 'CCPN %s - Attribute Map' % self.apiName
self.writeElementHeader(package, title, special='Attribute Map')
self.writeAttributeMap(package)
self.closeFile()
# write method map
fileName = Path.joinPath(self.rootDirName, self.topDocDir, self.methodMapPrefix)
self.openFile(fileName)
title = 'CCPN %s - Method Map' % self.apiName
self.writeElementHeader(package, title, special='Method Map')
self.writeMethodMap(package)
self.closeFile()
# write package diagram documentation
self.writeDiagramDocumentation(package)
###########################################################################
###########################################################################
# overrides ModelTraverse
[docs] def processLeafPackage(self, package):
""" processing actions for leaf package
"""
fileName = self.getObjDocFileName(package)
packageDirName = Path.splitPath(fileName)[0]
#print 'processLeafPackage', package.qualifiedName(), packageDirName
self.createDir(packageDirName)
self.openFile(fileName)
self.writeElementComment(package)
title = 'CCPN %s - %s' % (self.apiName, self.getImportName(package))
(prev, foll) = self.getPrevNextPackages(package)
self.writeElementHeader(package, title, prev=prev, foll=foll)
self.writeLeafPackage(package)
self.writeObjectFooter(package)
self.closeFile()
# write related files
elems = package.classes + package.dataObjTypes + package.dataTypes
elems = metaUtil.sortByAttribute(elems, 'name')
elems.insert(0, None)
elems.append(None)
for ii in range(1, len(elems)-1):
elem = elems[ii]
if isinstance(elem,MetaModel.MetaClass):
self.writeClassDocumentation(elem,elems[ii-1],elems[ii+1])
elif isinstance(elem,MetaModel.MetaDataObjType):
self.writeDataObjTypeDocumentation(elem,elems[ii-1],elems[ii+1])
elif isinstance(elem,MetaModel.MetaDataType):
self.writeDataTypeDocumentation(elem,elems[ii-1],elems[ii+1])
else:
raise MemopsError("Illegal type object found : %s" % elem)
# write package diagram documentation
self.writeDiagramDocumentation(package)
###########################################################################
###########################################################################
###
### internal code
###
###########################################################################
###########################################################################
[docs] def writeRootPackage(self, root):
""" write code for Root package
"""
topPath = self.pathToTop(root)
apiFileDir = Path.joinPath(self.pathToTop(root, upDir=2), self.baseDirName, self.apiFileDir)
diagImgDir = Path.joinPath(self.pathToTop(root, upDir=2), self.baseDirName, self.diagImgDir)
self.writeStartSection(cellpadding=5, width='100%')
self.writeHeading('%s Documentation' % self.apiName, level=1)
self.writePageDocString(root)
self.writeBreak()
self.writeStartTable(cellpadding=2, cellspacing=2)
self.writeStartRow(valign='top')
self.writeCell('See Also:')
self.writeNonBreakingSpaces(4)
self.writeStartCell()
self.writeLink(Path.joinPath(diagImgDir, self.indexFile), 'Documentation', target='blank')
self.write('for Data Model')
self.writeBreak()
self.writeLink(Path.joinPath(apiFileDir, 'quickguide.html'), 'Quick Guide',
target='blank')
self.write('to CCP software')
self.writeBreak()
self.writeLink(Path.joinPath(apiFileDir, 'api-description.html'), 'Overview',
target='blank')
self.write('of %s' % self.apiName)
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
self.writeBreak()
self.writeHeading('Directly Contained packages:', level=2)
self.writeStartTable(_class="elemtable")
self.writeStartRow()
self.writeCell('Package', _class='tblhead')
self.writeCell('Description', _class='tblhead')
self.writeEndRow()
directList = metaUtil.sortByAttribute(root.containedPackages, 'name')
# write directly contained packages
for pp in directList:
ss = Path.joinPath(topPath, self.fileFromTop(pp))
tt = self.getLinkString(ss, pp.name)
doc = self.getElemDocString(pp)
self.writeStartRow(valign='top')
self.writeCell(tt, _class='tblrow')
self.writeCell(doc, _class='tblrow')
self.writeEndRow()
self.writeEndTable()
self.writeBreak()
self.writeHorizontalLine()
# write all contained packages
self.writeBreak()
self.writeHeading('All Contained packages:', level=2)
for package in directList:
self.writeHeading('%s contains:' % package.name, level=3)
self.writeStartTable(cellpadding=2, cellspacing=2, _class="elemtable")
self.writeStartRow()
self.writeCell('Package', _class="tblhead")
self.writeCell('Description', _class="tblhead")
self.writeEndRow()
ll = metaUtil.sortByAttribute(package.containedPackages, 'name')
while ll:
pp = ll.pop()
ss = Path.joinPath(topPath, self.fileFromTop(pp))
tt = self.getLinkString(ss, self.getImportName(pp))
doc = self.getElemDocString(pp)
self.writeStartRow(valign='top')
self.writeCell(tt, _class='tblrow')
self.writeCell(doc, _class='tblrow')
self.writeEndRow()
ll.extend(metaUtil.sortByAttribute(pp.containedPackages, 'name'))
self.writeEndTable()
self.writeBreak()
self.writeEndSection()
self.writePackageGuid(root)
###########################################################################
###########################################################################
[docs] def writeClassMap(self, root):
# determine what should be listed
allAbstractDataTypes = []
self.determineAllAbstractDataTypes(root, allAbstractDataTypes)
# write content page
self.writeDoubleColPage('Class Map', root, allAbstractDataTypes)
###########################################################################
###########################################################################
[docs] def writeDoubleColPage(self, heading, root, elems):
self.writeStartTable(cellpadding=5, width='100%')
self.writeStartRow()
self.writeStartCell(colspan=2)
self.writeHeading(heading, level=1)
self.writeEndCell()
self.writeEndRow()
self.writeStartRow()
self.writeStartCell(colspan=2)
self.writeStartTable()
self.writeStartRow()
alphabet = string.ascii_uppercase
for letter in alphabet:
self.writeCell('%s%s' % (self.getNonBreakingSpaces(),
self.getLinkString('#letter%s' % letter, letter)))
self.writeEndRow()
self.writeEndTable()
self.writeEndCell()
self.writeEndRow()
topPath = self.pathToTop(root)
dd = {}
for elem in elems:
key = elem.name + '.' + elem.container.qualifiedName()
if isinstance(elem, MetaModel.MetaOperation) and not self.methodHasOwnPage(elem):
ee = elem.target
else:
ee = elem
link = Path.joinPath(topPath, self.fileFromTop(ee))
dd[key] = (link, self.getImportName(elem), elem.name)
self.writeStartRow(valign='top')
self.writeStartCell()
self.writeStartTable()
keys = list(dd.keys())
keys.sort()
i = 0
imax = len(keys)
countLetters = {}
for letter in alphabet:
countLetters[letter] = 0
self.writeStartRow()
ss = self.getStyleString(letter, style='font-weight: bold; foint-size: 12pt')
ss = '%s%s' % (self.getNonBreakingSpaces(), self.getAnchorLinkString('letter%s' % letter, ss))
self.writeCell(ss, _class='tblhead', colspan=3)
self.writeEndRow()
for key in keys:
if key[0].upper() == letter:
countLetters[letter] += 1
i += 1
if i == int (imax/2) + 10:
self.writeEndTable()
self.writeEndCell()
self.writeStartCell()
self.writeStartTable()
if countLetters[letter] > 1:
self.writeStartRow()
ss = self.getStyleString('%s ' % letter, style='font-weight: bold; font-size: 12pt;')
ss = '%s%s%s' % (self.getNonBreakingSpaces(), ss, 'continued')
self.writeCell(ss, _class='tblhead', colspan=3)
(link, longName, shortName) = dd[key]
self.writeStartRow()
self.writeCell(self.getNonBreakingSpaces(2))
self.writeCell(self.getSmallString(longName[:-len(shortName)]), align='right')
self.writeCell(self.getStyleString(self.getLinkString(link, shortName), style='font-size: 11pt'))
self.writeEndRow()
del dd[key]
self.writeStartRow()
self.writeCell(self.getNonBreakingSpaces())
self.writeEndRow()
##self.writeStartRow()
##ss = self.getStyleString('...', style='font-weight: bold; foint-size: 12pt')
##ss = '%s%s' % (self.getNonBreakingSpaces(), ss)
##self.writeCell(ss)
##self.writeEndRow()
keys = list(dd.keys())
keys.sort()
for key in keys:
(link, longName, shortName) = dd[key]
self.writeStartRow()
self.writeCell(self.getNonBreakingSpaces(2))
self.writeCell(self.getSmallString(longName[:-len(shortName)]), align='right')
self.writeCell(self.getStyleString(self.getLinkString(link, shortName), style='font-size: 11pt;'))
self.writeEndRow()
self.writeEndTable()
self.writeEndSection()
###########################################################################
###########################################################################
[docs] def writeAttributeMap(self, root):
# determine what should be listed
allAttrRoles = []
self.determineAllAttrRoles(root, allAttrRoles)
# write content page
self.writeDoubleColPage('Attribute Map', root, allAttrRoles)
###########################################################################
###########################################################################
[docs] def writeMethodMap(self, root):
# determine what should be listed
allMethods = []
self.determineAllMethods(root, allMethods)
# write content page
self.writeDoubleColPage('Method Map', root, allMethods)
###########################################################################
###########################################################################
[docs] def writeBranchPackage(self, package):
""" write code for non-Root branch packages
"""
topPath = self.pathToTop(package)
self.writeStartSection(cellpadding=5, width='100%')
# write page heading
self.writePageHeading(package, 'Package')
# write package documentation
self.writePageDocString(package)
# write directly contained packages
self.writeStartTable(cellpadding=2, cellspacing=2, _class="elemtable")
self.writeStartRow()
self.writeCell('Package', _class='tblhead')
self.writeCell('Description', _class='tblhead')
self.writeEndRow()
directList = metaUtil.sortByAttribute(package.containedPackages, 'name')
for pp in directList:
ss = Path.joinPath(topPath, self.fileFromTop(pp))
tt = self.getLinkString(ss, pp.name)
doc = self.getElemDocString(pp)
self.writeStartRow(valign='top')
self.writeCell(tt, _class='tblrow')
self.writeCell(doc, _class='tblrow')
self.writeEndRow()
self.writeEndTable()
self.writeEndSection()
self.writePackageGuid(package)
###########################################################################
###########################################################################
[docs] def writeLeafPackage(self, package):
""" write code for leaf packages
"""
self.writeStartSection(cellpadding=5, width="100%")
self.writeStartTable(cellpadding=2, cellspacing=2, width="100%")
self.writeStartRow(valign='top')
self.writeStartCell()
# write page heading
self.writePageHeading(package, 'Package')
# write package documentation
self.writePageDocString(package)
self.writeEndCell()
self.writeStartCell(width='20%', valign='top', align='right')
self.writeLink('#Classes', 'Classes')
self.writeBreak()
self.writeLink('#Data Types', 'Data Types')
self.writeBreak()
self.writeLink('#Data Obj Types', 'Data Obj Types')
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
for (packages, heading) in ((package.importedPackages, 'Imported Packages'),
(package.accessedPackages, 'Packages Importing %s' % self.getImportName(package))):
ll = [self.getLinkInfo(package,pp) for pp in packages]
self.writeBreak()
self.writeHeading('%s:' % heading, level=3)
if ll:
ll.sort()
ll2 = []
for (name, ref) in ll:
ss = self.getLinkString('%s/%s' % (ref, self.indexFile), name)
ll2.append(ss)
cc = ', %s\n' % self.getNonBreakingSpaces()
self.write(cc.join(ll2))
else:
self.write('None')
self.writeBreak()
self.writeEndSection()
classes = metaUtil.sortByAttribute(package.classes, 'name')
dataObjTypes = metaUtil.sortByAttribute(package.dataObjTypes, 'name')
dataTypes = metaUtil.sortByAttribute(package.dataTypes, 'name')
for (elems, heading) in ((classes, 'Classes'),
(dataObjTypes, 'Data Obj Types'),
(dataTypes, 'Data Types')):
self.writeStartSection(cellpadding=5, width="100%")
self.writeBreak()
self.writeAnchorLink(heading)
self.writeHeading('%s:' % heading, level=3)
self.writeStartTable(cellpadding=2, cellspacing=2, _class="elemtable")
self.writeStartRow()
if heading == 'Classes':
ss = 'Class'
else:
ss = 'Type'
self.writeCell(ss, _class='tblhead')
self.writeCell('Description', _class='tblhead')
self.writeEndRow()
if elems:
for elem in elems:
self.writeStartRow(valign='top')
if self.elemHasOwnDirectory(elem):
link = self.getLinkString('%s/%s' % (elem.name, self.indexFile), elem.name)
else:
link = self.getLinkString('%s.%s' % (elem.name, self.fileSuffix), elem.name)
self.writeCell(link, _class='tblrow')
doc = self.getElemDocString(elem)
self.writeCell(doc, _class='tblrow')
self.writeEndRow()
else:
self.writeStartRow()
self.writeCell('None', colspan=2, _class='tblrow')
self.writeEndRow()
self.writeEndTable()
self.writeEndSection()
self.writePackageGuid(package)
###########################################################################
###########################################################################
[docs] def writeRootPackageDiagram(self, package):
""" write code for diagram for root package
"""
# make table lists
lists = {}
for pkgGroup in pkgGroupOrder:
lists[pkgGroup] = []
for pp in self.diagramOrderedPackages:
if not pp.containedPackages:
# leaf package
pkgGroup = pp.taggedValues.get('packageGroup','core')
lists[pkgGroup].append(pp)
fileName = self.getDiagramFileName(package, isAbsolute=True)
pathList = self.getElementPathList(package)
pathList = pathList[:-1]
topPath = self.upDir(len(pathList))
self.openFile(fileName)
self.writeElementComment(package)
self.writeDiagramElementHeader(package)
self.writeStartTable(width="100%")
self.writeStartRow()
self.writeDiagramLeftBar(package, topPath)
self.writeStartCell(valign='top', align='left', width="100%")
self.writeHeading('Diagram Home', level=3)
self.writeStartParagraph()
self.writeStartTable(align='center')
self.writeStartRow()
self.writeStartCell(valign='middle')
self.writeStartTable()
self.writeStartRow(valign='top')
for pkgGroup in pkgGroupOrder:
ll = lists[pkgGroup]
if ll:
dd = pkgGroupData[pkgGroup]
self.writeStartCell()
self.writeStartDiv(_class='leftbanner')
self.writeStartTable(width=130, height=60)
self.writeStartRow()
self.writeCell(self.getNonBreakingSpaces(), width=1, _class=dd['htmlClass'])
self.writeCell(dd['homeTitle'], _class='space')
self.writeEndRow()
self.writeEndTable()
self.writeStartTable(width=150)
for pp in ll:
pathList = self.getElementPathList(pp)
pathList = pathList[:-1]
if pathList:
dirName = Path.joinPath(*pathList)
else:
dirName = ''
href = Path.joinPath(dirName, '%s.%s' % (pp.name, self.fileSuffix))
self.writeStartRow()
self.writeStartCell(_class=pkgGroupData[pkgGroup]['htmlClass'])
self.writeLink(href, pp.qualifiedName())
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
self.writeEndDiv()
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
self.writeEndParagraph()
self.writeStartParagraph()
self.write("""
This documentation may not cover all known model packages. Some diagrams may contain
classes from model packages that are not covered in the present documentation. If
so, you should assume that these classes are not relevant to your purpose.
""")
self.writeEndParagraph()
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
self.writeObjectFooter(package)
self.closeFile()
# extra files
self.writeDiagramHelp()
self.writeDiagramLicense()
###########################################################################
###########################################################################
[docs] def writeBranchPackageDiagram(self, package):
""" write code for diagram for non-root branch packages
"""
fileName = self.getDiagramFileName(package, isAbsolute=True)
pathList = self.getElementPathList(package)
topPath = self.upDir(len(pathList))
docDirName = Path.joinPath(self.rootDirName, self.modelDiagramDir)
self.openFile(fileName)
self.writeElementComment(package)
self.writeDiagramElementHeader(package)
self.writeStartTable(width="100%")
self.writeStartRow()
self.writeDiagramLeftBar(package, topPath)
self.writeStartCell(valign='top', align='left', width="100%")
self.writeHeading('Package: %s' % package.qualifiedName(), level=3)
self.write(self.getElemDocString(package))
self.writeStartCenter()
ss = package.taggedValues.get('docDiagramNames')
if ss:
diagNames = ss.split()
for diagName in diagNames:
diagFile = Path.joinPath(package.qualifiedName().replace('.', '_') + '_' + diagName + self.diagFileExt)
# diagFile = Path.joinPath(self.diagImgDir, package.qualifiedName().replace('.', '_') + '_' + diagName + self.diagFileExt)
file = Path.joinPath(docDirName, diagFile)
if not os.path.isfile(file):
print("WARNING1: File %s does not exist" % file)
diagFile = Path.joinPath(topPath, diagFile)
diagAlt = package.qualifiedName()
if diagName[0] == '_':
diagLegend = diagName[1:]
else:
diagLegend = diagName
self.writeBreak(2)
self.write(diagLegend)
self.writeBreak()
self.write(self.getImageString(src=diagFile, alt=diagAlt, border=0))
self.writeBreak(2)
self.writeEndCenter()
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
self.writeObjectFooter(package)
self.closeFile()
###########################################################################
###########################################################################
[docs] def writeLeafPackageDiagram(self, package):
""" write code for diagram for leaf branch packages
"""
# get diagram names to generate files from
diagNameDict = set()
dd = set([package.name])
ss = package.taggedValues.get('docDiagramNames')
n = len(self.detailDiagExt)
if ss:
for ss in ss.split():
diagNameDict.add(ss)
# strip leading underscore
ss = ss[1:]
if ss[-n:] == self.detailDiagExt:
ss = ss[:-n]
dd.add(ss)
diagramTags = list(dd)
diagramTags.sort()
# make files
for tag in diagramTags:
self.writeLeafPackageTagDiagram(package, tag, diagramTags)
###########################################################################
###########################################################################
[docs] def writeLeafPackageTagDiagram(self, package, tag, diagramTags):
pathList = self.getElementPathList(package)
pathList = pathList[:-1]
topPath = self.upDir(len(pathList))
docDirName = Path.joinPath(self.rootDirName, self.modelDiagramDir)
dirName = Path.joinPath(docDirName, *pathList)
pkgName = package.name
if not os.path.exists(dirName):
raise MemopsError('Directory "%s" does not exist' % dirName)
if tag == pkgName:
name = tag
else:
name = pkgName + '_' + tag
fileName = Path.joinPath(dirName, name)
self.openFile(fileName)
self.writeElementComment(package)
self.writeDiagramElementHeader(package)
self.writeStartTable(width="100%")
self.writeStartRow()
self.writeDiagramLeftBar(package, topPath)
self.writeStartCell(valign='top', align='left', width="100%")
self.writeHeading('Package: %s' % package.qualifiedName(), level=3)
self.write(self.getElemDocString(package))
# add menu for other diagrams
if len(diagramTags) > 1:
self.writeStartParagraph()
self.writeStartDiv(_class = 'topbanner')
self.writeStartTable(width='100%', border=0)
self.writeStartRow(valign='top')
self.writeStartCell(align='left', valign='bottom')
self.write('Class diagrams: { ')
tt = None
for ss in diagramTags:
if ss == pkgName:
name2 = ss
else:
name2 = pkgName + '_' + ss
href = '%s.%s' % (name2, self.fileSuffix)
if tt:
self.write(' | ')
if ss == tag:
tt = self.getStyleString(ss, _class='underover')
else:
tt = ss
self.writeLink(href, tt)
self.write('}')
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
self.writeEndDiv()
self.writeEndParagraph()
self.writeStartCenter()
# details diagram:
dDiagFile = ''.join((package.qualifiedName().replace('.', '_'),
'__', tag, self.detailDiagExt, self.diagFileExt))
# dDiagFile = Path.joinPath(self.diagImgDir,
# package.qualifiedName().replace('.', '_') + '__' + tag + self.detailDiagExt + self.diagFileExt)
file = Path.joinPath(docDirName, dDiagFile)
if os.path.isfile(file):
path = Path.joinPath(topPath, dDiagFile)
self.writeLink("javascript:wopn('%s')" % path, self.getItalicString('click here to see the detailed diagram'))
else:
print('WARNING2: File "%s" does not exist' % file)
# normal diagram
# dDiagFile = Path.joinPath(self.diagImgDir,
# package.qualifiedName().replace('.', '_') + '__' + tag + self.diagFileExt)
dDiagFile = package.qualifiedName().replace('.', '_') + '__' + tag + self.diagFileExt
file = Path.joinPath(docDirName, dDiagFile)
if os.path.isfile(file):
src = Path.joinPath(topPath, dDiagFile)
alt = package.qualifiedName() + tag + ' class diagram'
self.writeBreak()
self.write(self.getImageString(src=src, alt=alt, border=0))
else:
print('WARNING3: File "%s" does not exist' % file)
self.writeEndCenter()
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
self.writeObjectFooter(package)
self.closeFile()
###########################################################################
###########################################################################
[docs] def writeDiagramHelp(self):
docDirName = Path.joinPath(self.rootDirName, self.modelDiagramDir)
fileName = Path.joinPath(docDirName, self.helpPrefix)
self.openFile(fileName)
self.writeComment('Help')
self.writeDiagramElementHeader(special='Help')
self.writeStartTable(width="100%")
self.writeStartRow()
topPath = self.upDir(0) # HACK for Help and License
self.writeDiagramLeftBar(topPath=topPath)
self.writeStartCell(valign='top', align='left', width='100%')
self.writeDiagramHelpContent()
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
self.writeObjectFooter()
self.closeFile()
###########################################################################
###########################################################################
[docs] def writeDiagramLicense(self):
docDirName = Path.joinPath(self.rootDirName, self.modelDiagramDir)
fileName = Path.joinPath(docDirName, self.licensePrefix)
self.openFile(fileName)
self.writeComment('License')
self.writeDiagramElementHeader(special='License')
self.writeStartTable(width="100%")
self.writeStartRow()
topPath = self.upDir(0) # HACK for Help and License
self.writeDiagramLeftBar(topPath=topPath)
self.writeStartCell(valign='top', align='left', width='100%')
self.writeGnuLicense()
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
self.writeObjectFooter()
self.closeFile()
###########################################################################
###########################################################################
[docs] def writeDiagramLeftBar(self, package = None, topPath = ''):
""" write bar at left for diagram pages
"""
self.writeStartCell(valign='top')
self.writeStartDiv(_class='leftbanner')
self.writeStartTable(width=130)
firstTime = True
for pp in self.diagramOrderedPackages:
if pp.container:
label = pp.name
else:
label = 'Diagram Home'
if pp is package:
label = self.getStyleString(label, _class='underover')
if pp.containedPackages:
# branch package
if not firstTime:
self.writeStartRow(height=10)
self.writeCell(_class='space')
self.writeEndRow()
pathList = self.getElementPathList(pp)
if not pp.container:
pathList = pathList[:-1]
dirname = Path.joinPath(topPath, *pathList)
href = Path.joinPath(dirname, self.indexFile)
self.writeStartRow()
self.writeCell(self.getLinkString(href, label), colspan=2)
self.writeEndRow()
else:
# leaf package
pathList = self.getElementPathList(pp)
pathList = pathList[:-1]
dirname = Path.joinPath(topPath, *pathList)
href = Path.joinPath(dirname, '%s.%s' % (pp.name, self.fileSuffix))
pkgGroup = pp.taggedValues.get('packageGroup','core')
ss = pkgGroupData[pkgGroup]['htmlClass']
self.writeStartRow()
self.writeCell(self.getNonBreakingSpaces(), _class=ss, width=1)
self.writeCell(self.getLinkString(href, label))
self.writeEndRow()
firstTime = False
self.writeEndTable()
self.writeEndDiv()
self.writeEndCell()
###########################################################################
###########################################################################
[docs] def writePackageGuid(self, package):
self.writeHorizontalLine()
self.writeStartSection(cellpadding=5, width="100%")
self.writeStartTable(cellpadding=2, cellspacing=2)
self.writeStartRow(valign='top')
self.writeCell('%s%s' % (self.getBreakString(), self.getStrongString('Package guid:')))
self.writeCell('%s%s' % (self.getBreakString(), package.guid))
self.writeEndRow()
self.writeEndTable()
self.writeEndSection()
###########################################################################
###########################################################################
[docs] def writeClassDocumentation(self, clazz, prev, foll):
fileName = self.getObjDocFileName(clazz)
directory = Path.splitPath(fileName)[0]
self.createDir(directory)
self.openFile(fileName)
title = 'CCPN %s Class: %s' % (self.apiName, clazz.name)
self.writeElementHeader(clazz, title, prev, foll)
self.writeClass(clazz)
self.writeObjectFooter(clazz)
self.closeFile()
# write related files
ll = clazz.attributes + clazz.roles
ll = metaUtil.sortByAttribute(ll, 'name')
ll.insert(0,None)
ll.append(None)
for ii in range(1,len(ll)-1):
self.writeAttrDocumentation(ll[ii], ll[ii-1], ll[ii+1])
ll = [ op for op in clazz.operations if self.methodHasOwnPage(op) ]
ll = metaUtil.sortByAttribute(ll, 'name')
ll.insert(0,None)
ll.append(None)
for ii in range(1,len(ll)-1):
self.writeMethodDocumentation(ll[ii], ll[ii-1], ll[ii+1])
###########################################################################
###########################################################################
[docs] def writeDataObjTypeDocumentation(self, dataObjType, prev, foll):
fileName = self.getObjDocFileName(dataObjType)
directory = Path.splitPath(fileName)[0]
self.createDir(directory)
self.openFile(fileName)
title = 'CCPN %s Data ObjType: %s' % (self.apiName, dataObjType.name)
self.writeElementHeader(dataObjType, title, prev, foll)
self.writeDataObjType(dataObjType)
self.writeObjectFooter(dataObjType)
self.closeFile()
# write related files
ll = dataObjType.attributes
ll = metaUtil.sortByAttribute(ll, 'name')
ll.insert(0,None)
ll.append(None)
for ii in range(1,len(ll)-1):
self.writeAttrDocumentation(ll[ii], ll[ii-1], ll[ii+1])
ll = [ op for op in dataObjType.operations if self.methodHasOwnPage(op) ]
ll = metaUtil.sortByAttribute(ll, 'name')
ll.insert(0,None)
ll.append(None)
for ii in range(1,len(ll)-1):
self.writeMethodDocumentation(ll[ii], ll[ii-1], ll[ii+1])
###########################################################################
###########################################################################
[docs] def writeDataTypeDocumentation(self, dataType, prev, foll):
fileName = self.getObjDocFileName(dataType)
directory = Path.splitPath(fileName)[0]
self.createDir(directory)
self.openFile(fileName)
title = 'CCPN %s Data Type: %s' % (self.apiName, dataType.name)
self.writeElementHeader(dataType, title, prev, foll)
self.writeDataType(dataType)
self.writeObjectFooter(dataType)
self.closeFile()
###########################################################################
###########################################################################
# previously called writeElemDocumentation
[docs] def writeAttrDocumentation(self, elem, prev, foll):
fileName = self.getObjDocFileName(elem)
#print 'writeElemDocumentation', elem.qualifiedName(), fileName
self.openFile(fileName)
title = 'CCPN %s Attribute: %s' % (self.apiName, self.getImportName(elem))
##self.writeElementHeader(elem, title, prev, foll, attributeLetter=elem.name[0].upper())
self.writeElementHeader(elem, title, prev, foll)
self.writeAttributePage(elem)
self.writeObjectFooter(elem.container)
self.closeFile()
###########################################################################
###########################################################################
# previously called writeOpDocumentation
[docs] def writeMethodDocumentation(self, elem, prev, foll):
fileName = self.getObjDocFileName(elem)
#print 'writeElemDocumentation', elem.qualifiedName(), fileName
self.openFile(fileName)
title = 'CCPN %s Method: %s' % (self.apiName, self.getImportName(elem))
self.writeElementHeader(elem, title, prev, foll)
self.writeMethodPage(elem)
self.writeObjectFooter(elem.container)
self.closeFile()
###########################################################################
###########################################################################
[docs] def writeClass(self, clazz):
self.writeStartSection(cellpadding=5, width="100%")
self.writeStartTable(cellpadding=2, cellspacing=2, width='100%')
self.writeStartRow(valign='top')
self.writeStartCell()
# write page heading
self.writePageHeading(clazz, 'Class')
if clazz.isAbstract:
self.writeBreak()
self.writeEmphasisString('Abstract Class')
self.writeBreak()
if (self.handCodeKey in clazz.constructorCodeStubs or
self.handCodeKey in clazz.postConstructorCodeStubs):
self.writeEmphasisString('The %s constructor includes non-standard actions.' % clazz.name)
if (self.handCodeKey in clazz.destructorCodeStubs or
self.handCodeKey in clazz.postDestructorCodeStubs):
self.writeEmphasisString('The %s destructor includes non-standard actions.' % clazz.name)
# write class documentation
self.writePageDocString(clazz)
self.writeEndCell()
self.writeStartCell(width='20%', valign='top', align='right')
self.writeLink('#Attributes', 'Attributes')
self.writeBreak()
self.writeLink('#Link Attributes', 'Link Attributes')
self.writeBreak()
self.writeLink('#Attribute Methods', 'Attribute Methods')
self.writeBreak()
self.writeLink('#Link Attribute Methods', 'Link Attribute Methods')
self.writeBreak()
self.writeLink('#Class Methods', 'Class Methods')
self.writeBreak()
self.writeLink('#Factory Methods', 'Factory Methods')
self.writeBreak()
self.writeLink('#Other Methods', 'Other Methods')
self.writeBreak()
self.writeLink('#Appendix', 'Appendix')
self.writeBreak()
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
self.writeEndSection()
self.writeStartSection(cellpadding=5, width="100%")
# Inheritance
self.writeInheritanceDiagram(clazz)
# Details
self.writeBreak()
self.writeHeading('Details:', level=3)
self.writeStartTable(cellpadding=2, cellspacing=2)
# Parent
self.writeStartRow()
self.writeCell('Parent:')
self.writeCell(self.getParentString(clazz))
self.writeEndRow()
# Main key
if clazz.keyNames:
ss = self.getEmphasisString(', '.join(clazz.keyNames))
else:
ss = 'n/a'
self.writeStartRow()
self.writeCell('Main key:')
self.writeCell(ss)
self.writeEndRow()
# Mandatory Attributes
mandatoryElements, hasOptionals = self.getMandatoryElements(clazz)
if mandatoryElements:
ss = self.getEmphasisString(', '.join(mandatoryElements))
else:
ss = 'None'
self.writeStartRow()
self.writeCell('Mandatory Attributes:')
self.writeCell(ss)
self.writeEndRow()
# Partitions children
# for now only if true
if clazz.partitionsChildren:
self.writeStartRow()
self.writeCell('Partitions Children:')
self.writeCell(str(clazz.partitionsChildren))
self.writeEndRow()
# Known Subclasses
subtypes = clazz.subtypes
if subtypes:
ll = [self.getLinkInfo(clazz, x) for x in subtypes]
ll.sort()
links = [ self.getLinkString(Path.joinPath(ref, self.indexFile), name) for (name, ref) in ll ]
ss = ', '.join(links)
else:
ss = 'None'
self.writeStartRow()
self.writeCell('Known Subclasses:')
self.writeCell(ss)
self.writeEndRow()
# Children
childRoles = [ role for role in clazz.getAllRoles() if role.hierarchy == metaConstants.child_hierarchy ]
if childRoles:
childRoles = metaUtil.sortByAttribute(childRoles, 'name')
self.writeStartRow(valign='top')
self.writeCell('Children:')
self.writeStartCell()
self.writeStartTable(cellpadding=2, cellspacing=2)
for childRole in childRoles:
child = childRole.valueType
self.writeStartRow()
self.writeCell('link')
self.writeCell(self.getEmphasisString(childRole.name))
(name, ref) = self.getLinkInfo(clazz, child)
self.writeCell('to%sclass' % self.getNonBreakingSpaces())
self.writeCell(self.getLinkString(Path.joinPath(ref, self.indexFile), name))
self.writeEndRow()
self.writeEndTable()
self.writeEndCell()
self.writeEndRow()
else:
self.writeStartRow()
self.writeCell('Children:')
self.writeCell('None', colspan=4)
self.writeEndRow()
# Constructor
if not clazz.isAbstract:
self.writeConstructorRows(clazz, mandatoryElements)
self.writeEndTable()
self.writeEndSection()
# Attributes
self.writeAttributeTable(clazz, 'attrs')
# Link attributes
self.writeAttributeTable(clazz, 'links')
# Methods
self.writeMethodTables(clazz)
# Appendix
self.writeAppendix(clazz)
###########################################################################
###########################################################################
[docs] def writeDataObjType(self, dataObjType):
self.writeStartSection(cellpadding=5, width="100%")
self.writeStartTable(cellpadding=2, cellspacing=2, width='100%')
self.writeStartRow(valign='top')
self.writeStartCell()
# write page heading
self.writePageHeading(dataObjType, 'Data Obj Type')
if dataObjType.isAbstract:
self.writeBreak()
self.writeEmphasisString('Abstract Data Obj Type')
self.writeBreak()
# write data obj type documentation
self.writePageDocString(dataObjType)
self.writeEndCell()
self.writeStartCell(width='20%', valign='top', align='right')
self.writeLink('#Attributes', 'Attributes')
self.writeBreak()
self.writeLink('#Attribute Methods', 'Attribute Methods')
self.writeBreak()
self.writeLink('#Class Methods', 'Class Methods')
self.writeBreak()
self.writeLink('#Other Methods', 'Other Methods')
self.writeBreak()
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
self.writeEndSection()
self.writeStartSection(cellpadding=5, width="100%")
# Inheritance
self.writeInheritanceDiagram(dataObjType)
# Details
self.writeBreak()
self.writeHeading('Details:', level=3)
self.writeStartTable(cellpadding=2, cellspacing=2)
# isChangeable
self.writeStartRow()
self.writeCell('isChangeable:')
self.writeCell(str(dataObjType.isChangeable))
self.writeEndRow()
# Mandatory Attributes
mandatoryElements, hasOptionals = self.getMandatoryElements(dataObjType)
if mandatoryElements:
ss = self.getEmphasisString(', '.join(mandatoryElements))
else:
ss = 'None'
self.writeStartRow()
self.writeCell('Mandatory Attributes:')
self.writeCell(ss)
self.writeEndRow()
# Known Subtypes
subtypes = dataObjType.subtypes
if subtypes:
ll = [self.getLinkInfo(dataObjType, x) for x in subtypes]
ll.sort()
links = [ self.getLinkString(Path.joinPath(ref, self.indexFile), name) for (name, ref) in ll ]
ss = ', '.join(links)
else:
ss = 'None'
self.writeStartRow()
self.writeCell('Known Subtypes:')
self.writeCell(ss)
self.writeEndRow()
# Constructor
if not dataObjType.isAbstract:
self.writeConstructorRows(dataObjType, mandatoryElements)
self.writeEndTable()
self.writeEndSection()
# Attributes
self.writeAttributeTable(dataObjType, 'attrs')
# Methods
self.writeMethodTables(dataObjType)
# Appendix
self.writeAppendix(dataObjType)
self.writeBreak()
self.writeEndSection()
###########################################################################
###########################################################################
[docs] def writeDataType(self, dataType):
self.writeStartSection(cellpadding=5, width="100%")
# write page heading
self.writePageHeading(dataType, 'Data Type')
typeCode = dataType.typeCodes[self.typeCodeKey]
self.writeStartTable(cellpadding=2, cellspacing=2)
self.writeStartRow()
self.writeCell('Implementation%sType:' % self.getNonBreakingSpaces())
self.writeCell(typeCode)
self.writeEndRow()
package = dataType.container
supertypes = dataType.supertypes
if supertypes:
topPath = self.pathToTop(package)
ll = []
for supertype in supertypes:
if supertype.container is package:
ss = '%s.%s' % (supertype.name, self.fileSuffix)
else:
ss = Path.joinPath(topPath, self.fileFromTop(supertype))
tt = self.getBreakString() + self.getLinkString(ss, supertype.qualifiedName())
ll.append(tt)
if len(ll) == 1:
ss = ''
else:
ss = 's'
self.writeStartRow()
self.writeCell('%sSupertype%s:' % (self.getBreakString(), ss))
self.writeCell('%s%s' % (self.getBreakString(), ', '.join(ll)))
self.writeEndRow()
if typeCode == metaConstants.string_code:
maxlength = dataType.length
if maxlength is None or maxlength == metaConstants.infinity:
maxlength = 'unlimited'
self.writeStartRow()
self.writeCell('%sMaximum%slength:' % (self.getBreakString(), self.getNonBreakingSpaces()))
self.writeCell('%s%s' % (self.getBreakString(), maxlength))
self.writeEndRow()
if dataType.enumeration:
if dataType.isOpen:
ss = 'Open'
tt = 'Preset'
else:
ss = 'Closed'
tt = 'Permitted'
self.writeStartRow()
self.writeCell('%s%s%sEnumeration:' % (self.getBreakString(), ss, self.getNonBreakingSpaces()))
self.writeCell('%s%s%sValues: %s' % (self.getBreakString(), tt, self.getNonBreakingSpaces(), dataType.enumeration))
self.writeEndRow()
constraints = dataType.getAllConstraints()
if constraints:
constraints = metaUtil.sortByAttribute(constraints, 'name')
for constraint in constraints:
self.writeStartRow(valign='top')
self.writeCell('%sConstraint%sname:' % (self.getBreakString(), self.getNonBreakingSpaces()))
self.writeCell('%s%s' % (self.getBreakString(), constraint.name))
self.writeEndRow()
self.writeStartRow(valign='top')
self.writeCell('%s code' % self.handCodeKey, align='right')
self.writeCell(constraint.codeStubs.get(self.handCodeKey))
self.writeEndRow()
else:
self.writeStartRow()
self.writeCell('%sConstraints:' % self.getBreakString())
self.writeCell('%sNone' % self.getBreakString())
self.writeEndRow()
self.writeEndTable()
self.writeBreak()
self.writeEndSection()
###########################################################################
###########################################################################
[docs] def writeAttributePage(self, elem):
self.writeStartSection(cellpadding=5, width="100%")
if isinstance(elem,MetaModel.MetaAttribute):
elemType = 'Attribute'
else:
elemType = 'Link Attribute'
self.writePageHeading(elem, elemType)
if isinstance(elem,MetaModel.MetaRole):
ll = []
if elem.isAbstract:
ll.append('Abstract')
if elem.hierarchy == metaConstants.parent_hierarchy:
ll.append("Parent")
elif elem.hierarchy == metaConstants.child_hierarchy:
ll.append("Child")
if ll:
ll.append('Link')
self.writeEmphasisString(' '.join(ll))
self.writeBreak()
self.writeBreak()
# write attribute documentation
self.writePageDocString(elem)
# write details
self.writeBreak()
self.writeStartTable(cellpadding=2, cellspacing=2)
# guid
self.writeStartRow()
self.writeCell('guid:')
self.writeCell(elem.guid)
self.writeEndRow()
valueType = elem.valueType
haveImplType = False
if isinstance(valueType, MetaModel.MetaDataType):
typeCode = valueType.typeCodes[self.typeCodeKey]
if valueType.name != typeCode:
haveImplType = True
# Model Type (or just Type)
self.writeStartRow()
if haveImplType:
tt = 'Model '
else:
tt = ''
self.writeCell('%sType:' % tt)
self.writeCell(self.getElemTypeString(elem))
self.writeEndRow()
# Implementation Type
if haveImplType:
self.writeStartRow()
self.writeCell('Implementation Type:')
self.writeCell(typeCode)
self.writeEndRow()
# multiplicity, changeability, isDerived, isAutomatic, isImplementation, isImplicit, isAbstract, scope
for (ss, tt) in (('Multiplicity', self.getMultiplicity(elem)),
('Changeability', elem.changeability),
('isDerived', elem.isDerived),
('isAutomatic', elem.isAutomatic),
('isImplementation', elem.isImplementation),
('isImplicit', elem.isImplicit),
('isAbstract', elem.isAbstract),
('Scope', elem.scope)):
self.writeStartRow()
self.writeCell('%s:' % ss)
self.writeCell(str(tt))
self.writeEndRow()
# isOrdered, isUnique
if elem.hicard != 1:
for (ss, tt) in (('isOrdered', elem.isOrdered),
('isUnique', elem.isUnique)):
tt = str(tt)
self.writeStartRow()
self.writeCell('%s:' % ss)
self.writeCell(str(tt))
self.writeEndRow()
# default value
if isinstance(elem,MetaModel.MetaAttribute):
self.writeStartRow()
self.writeCell('Default Value:')
if elem.hicard == 1:
if elem.defaultValue:
dd = elem.defaultValue[0]
else:
dd = 'None'
else:
dd = elem.defaultValue
self.writeCell(self.normaliseString(str(dd)))
self.writeEndRow()
constraints = elem.getAllConstraints()
if constraints:
constraints = metaUtil.sortByAttribute(constraints, 'name')
for constraint in constraints:
self.writeStartRow(valign='top')
self.writeCell('%sConstraint name:' % self.getBreakString())
self.writeCell('%s%s' % (self.getBreakString(), constraint.name))
self.writeEndRow()
self.writeStartRow(valign='top')
self.writeCell('%s code' % self.handCodeKey, align='right')
ss = constraint.codeStubs.get(self.handCodeKey)
ss = self.normaliseString(ss)
self.writeCell(ss)
self.writeEndRow()
else:
self.writeStartRow()
self.writeCell('Constraints:')
self.writeCell('None')
self.writeEndRow()
else: # isinstance(elem,MetaModel.MetaRole)
if elem.hierarchy != metaConstants.no_hierarchy:
self.writeStartRow()
self.writeCell('Object hierarchy:')
self.writeCell(elem.hierarchy)
self.writeEndRow()
otherRole = elem.otherRole
if otherRole is None:
self.writeStartRow()
self.writeCell('Inverse role:')
self.writeCell('None')
self.writeEndRow()
else:
(name, ref) = self.getLinkInfo(elem.container, otherRole)
self.writeStartRow()
self.writeCell('Inverse role:')
self.writeCell(self.getLinkString('%s.%s' % (ref, self.fileSuffix), name))
self.writeEndRow()
constraints = elem.getAllConstraints()
if constraints:
constraints = metaUtil.sortByAttribute(constraints, 'name')
for constraint in constraints:
self.writeStartRow(valign='top')
self.writeCell('%sConstraint name:' % self.getBreakString())
self.writeCell('%s%s' % (self.getBreakString(), constraint.name))
self.writeEndRow()
self.writeStartRow(valign='top')
self.writeCell('%s code' % self.handCodeKey, align='right')
ss = constraint.codeStubs.get(self.handCodeKey)
ss = self.normaliseString(ss)
self.writeCell(ss)
self.writeEndRow()
if otherRole is not None and otherRole.getAllConstraints():
self.writeStartRow()
self.writeCell('Constraints:')
self.writeCell('See also Inverse Role')
self.writeEndRow()
elif otherRole is not None and otherRole.getAllConstraints():
self.writeStartRow()
self.writeCell('Constraints:')
self.writeCell('See Inverse Role')
self.writeEndRow()
else:
self.writeStartRow()
self.writeCell('Constraints:')
self.writeCell('None')
self.writeEndRow()
self.writeEndTable()
self.writeBreak()
# add tagged values
items = list(elem.taggedValues.items())
if items:
items.sort()
self.writeStartTable(cellpadding=2, cellspacing=2)
self.writeStartRow()
self.writeCell('Tag')
self.writeCell('Value')
self.writeEndRow()
for item in items:
(tag, value) = item
self.writeStartRow(valign='top')
self.writeCell(tag)
self.writeCell(value)
self.writeEndRow()
self.writeEndTable()
self.writeBreak()
self.writeEndSection()
self.writeHorizontalLine()
self.writeStartSection(cellpadding=5, width="100%")
self.writeHeading('Methods', level=3)
self.writeStartTable(cellpadding=2, cellspacing=2, _class='elemtable')
self.writeStartRow()
self.writeCell('Method', align='left', _class='tblhead')
self.writeCell('Return', align='left', _class='tblhead')
self.writeCell('Parameters', align='left', _class='tblhead')
self.writeCell('Comment', align='left', _class='tblhead')
self.writeEndRow()
nonStdString = self.getStrongString('Non-std.')
# TBD: below should maybe be Java specific but in current
# data model no methods end up using this in any case
classString = self.getStrongString('Static')
methods = self.getElemMethods(elem)
for method in methods:
self.writeStartRow()
if self.methodHasOwnPage(method):
(name, ref) = self.getLinkInfo(elem.container, method)
ss = self.getLinkString('%s.%s' % (ref, self.fileSuffix), self.getFuncname(method))
else:
ss = self.getFuncname(method)
self.writeCell(ss, _class='tblrow')
# Return
self.writeCell(self.getMethodReturn(method), _class='tblrow')
# Parameters
self.writeCell(self.getMethodParameters(method), _class='tblrow')
# Comment
ll = []
if method.scope == metaConstants.classifier_level:
ll.append(classString)
if not method.isImplicit:
ll.append(nonStdString)
ss = self.getNonBreakingSpaces()
ss = ss.join(ll)
self.writeCell(ss, _class='tblrow')
self.writeEndRow()
self.writeEndTable()
self.writeEndSection()
###########################################################################
###########################################################################
[docs] def writeMethodPage(self, elem):
self.writeStartSection(cellpadding=5, width="100%")
self.writePageHeading(elem, 'Method')
if elem.isAbstract:
self.writeBreak()
self.writeEmphasisString('Abstract Method')
self.writeBreak()
self.writeBreak()
# write operation documentation
self.writePageDocString(elem)
# guid, isQuery, isAbstract, scope
self.writeBreak()
self.writeStartTable(cellpadding=2, cellspacing=2)
for ss in ('guid', 'OpType', 'OpSubType', 'isQuery', 'isAbstract', 'Scope'):
self.writeStartRow()
self.writeCell('%s:' % ss)
self.writeCell(str(getattr(elem, metaUtil.lowerFirst(ss))))
self.writeEndRow()
# Code
ss = elem.codeStubs.get(self.handCodeKey)
ss = self.normaliseString(ss)
self.writeStartRow()
self.writeCell('Code:', valign='top')
self.writeCell(ss, valign='top')
self.writeEndRow()
self.writeEndTable()
self.writeEndSection()
###########################################################################
###########################################################################
# previously called writeModellerInfo
[docs] def writeAppendix(self, complexDataType):
toplinkString = 'Go%sto%sTop' % (self.getNonBreakingSpaces(), self.getNonBreakingSpaces())
toplinkString = self.getLinkString('#toplink', self.getStyleString(toplinkString, style='font-size:9pt'))
self.writeHorizontalLine()
self.writeStartSection(cellpadding=5, width="100%")
self.writeAnchorLink('Appendix')
self.writeHeading('Appendix', level=3)
self.writeStartTable(cellpadding=2, cellspacing=2, width='100%')
self.writeStartRow(valign='center')
self.writeCell(toplinkString, align='right')
self.writeEndRow()
self.writeEndTable()
self.writeStartTable(cellpadding=2, cellspacing=2)
# isImplicit, guid
for ss in ('guid', 'isImplicit'):
self.writeStartRow(valign='top')
self.writeCell('%s%s' % (self.getBreakString(), self.getStrongString('%s:' % ss)))
self.writeCell('%s%s' % (self.getBreakString(), getattr(complexDataType, ss)))
self.writeEndRow()
# Tagged Values
taggedValues = complexDataType.taggedValues
if taggedValues:
#print 'TAGGED VALUES', complexDataType.qualifiedName()
keys = list(taggedValues.keys())
keys.sort()
for key in keys:
self.writeStartRow(valign='top')
self.writeCell('%s%s' % (self.getBreakString(), self.getStrongString('Tag')))
self.writeCell('%s%s' % (self.getBreakString(), self.getStrongString('Value')))
self.writeEndRow()
self.writeStartRow(valign='top')
self.writeCell(key)
self.writeCell(taggedValues[key])
self.writeEndRow()
else:
self.writeStartRow(valign='top')
self.writeCell('%s%s' % (self.getBreakString(), self.getStrongString('Tagged Values:')))
self.writeCell('%sNone' % self.getBreakString())
self.writeEndRow()
# Special constructor code
ss = (complexDataType.constructorCodeStubs.get(self.handCodeKey, ''))
if isinstance(complexDataType, MetaModel.MetaClass):
ss += complexDataType.postConstructorCodeStubs.get(self.handCodeKey, '')
if ss:
#print 'CONSTRUCTOR', complexDataType.qualifiedName()
ss = self.normaliseString(ss)
else:
ss = 'None'
self.writeStartRow(valign='top')
self.writeCell('%s%s' % (self.getBreakString(), self.getStrongString('Special constructor code:')), valign='top')
self.writeCell('%s%s' % (self.getBreakString(), ss), valign='top')
self.writeEndRow()
# Special destructor code
if isinstance(complexDataType, MetaModel.MetaClass):
for tag in ('destructor','postDestructor'):
ss = getattr(complexDataType, tag + 'CodeStubs').get(self.handCodeKey)
if ss:
#print 'DESTRUCTOR', tag, complexDataType.qualifiedName()
ss = self.normaliseString(ss)
else:
ss = 'None'
self.writeStartRow(valign='top')
self.writeCell('%s%s' % (self.getBreakString(),
self.getStrongString('Special %s code:' % tag)), valign='top')
self.writeCell('%s%s' % (self.getBreakString(), ss), valign='top')
self.writeEndRow()
# Constraints
constraints = complexDataType.getAllConstraints()
if constraints:
#print 'CONSTRAINTS', complexDataType.qualifiedName(), len(constraints)
constraints = metaUtil.sortByAttribute(constraints, 'name')
for constraint in constraints:
self.writeStartRow(valign='top')
self.writeCell('%s%s' % (self.getBreakString(), self.getStrongString('Constraint name:')), valign='top')
self.writeCell('%s%s' % (self.getBreakString(), constraint.name), valign='top')
self.writeEndRow()
self.writeStartRow(valign='top')
self.writeCell(self.getStrongString('Constraint code:'), valign='top')
ss = constraint.codeStubs.get(self.handCodeKey)
ss = self.normaliseString(ss)
self.writeCell(ss, valign='top')
self.writeEndRow()
else:
self.writeStartRow()
self.writeCell('%s%s' % (self.getBreakString(), self.getStrongString('Constraints:')), valign='top')
self.writeCell('%sNone' % self.getBreakString(), valign='top')
self.writeEndRow()
# Added dataType use and inward one-way links
self.writeStartRow(valign='top')
if isinstance(complexDataType, MetaModel.MetaClass):
self.writeCell(self.getStrongString('Known inward one-way links:'),
valign='top')
else:
self.writeCell(self.getStrongString('Attributes using DataObjType:'),
valign='top')
valueTypeUse = self.valueTypeUse.get(complexDataType)
if valueTypeUse:
valueTypeUse.sort(key=MetaModel.MetaModelElement.qualifiedName)
ll = []
for ee in valueTypeUse:
(name, ref) = self.getLinkInfo(complexDataType, ee)
ll.append(self.getLinkString('%s.%s' % (ref, self.fileSuffix), name))
tt = ',' + self.getNonBreakingSpaces() + '\n'
self.writeCell(tt.join(ll), valign='top')
else:
self.writeCell('None', valign='top')
self.writeEndRow()
self.writeEndTable()
self.writeEndSection()
###########################################################################
###########################################################################
[docs] def writePageDocString(self, elem):
doc = self.getElemDocString(elem)
if doc:
self.writeBreak()
self.writeStartIndent()
self.write(doc)
self.writeEndIndent()
#elif isinstance(elem, MetaModel.MetaPackage) or isinstance(elem, MetaModel.MetaClass):
elif elem.container and elem.container.documentation:
print("WARNING, %s has no documentation" % elem.qualifiedName())
###########################################################################
###########################################################################
[docs] def getDiagramFileName(self, elem, isAbsolute):
""" Get the path for the diagram documentation for given element
"""
if isAbsolute:
topPath = self.rootDirName
else:
topPath = self.pathToTop(elem, upDir=2)
# diapackage is needed to establish the ink to Diagram
diapackage = elem
while not isinstance(diapackage,MetaModel.MetaPackage):
diapackage = diapackage.container
if elem.container is None:
# root package
diapath = Path.joinPath(topPath,'%s/%s' % (self.modelDiagramDir, self.indexPrefix))
elif isinstance(elem,MetaModel.MetaPackage) and elem.containedPackages:
# branch package
ll = diapackage.qualifiedName().split('.')
ll.append(self.indexPrefix)
diapath = Path.joinPath(topPath,self.modelDiagramDir,*ll)
else:
# leaf package or package content
ll = diapackage.qualifiedName().split('.')
diapath = Path.joinPath(topPath,self.modelDiagramDir, *ll)
return diapath
###########################################################################
###########################################################################
###def writeNavigatorBar(self, elem, prev = None, foll = None, special = None, upDir = 0, attributeLetter = 'A'):
[docs] def writeNavigatorBar(self, elem, prev = None, foll = None, special = None):
"""write javastyle navigator bar
The exact look is adjusted depending on the type of elem.
prev and foll are objects pointed to by the 'previous' and 'foll'
links, and should be of appropriate type.
"""
## upDir is hack to get Attribute Map pages to work
##self.writeCommonNavigatorBar(elem, upDir=upDir)
self.writeCommonNavigatorBar(elem)
##topPath = self.pathToTop(elem, upDir=upDir)
topPath = self.pathToTop(elem, upDir=2)
topDocPath = self.pathToTop(elem)
diapath = self.getDiagramFileName(elem, isAbsolute=False)
apiFileDir = Path.joinPath(topPath, self.baseDirName, self.apiFileDir)
apiDocDir = Path.joinPath(topPath, self.topDocDir)
self.writeStartRow()
self.writeStartCell(align='center')
self.writeLink('%s.%s' % (diapath, self.fileSuffix), 'Diagram')
self.writeVerticalBar()
if special == 'Class Map':
self.writeStyleString('Class Map', _class='underover')
else:
self.writeLink(Path.joinPath(apiDocDir, self.classMapFile), 'Class Map')
self.writeVerticalBar()
if special == 'Attribute Map':
self.writeStyleString('Attribute Map', _class='underover')
else:
## bit of a hack, assumes that will have something on A page
##ff = '%s.%s' % (attributeLetter, self.fileSuffix)
##self.writeLink(uniIo.joinPath(topPath, self.topDocDir, self.attrRoleDir, ff), 'Attribute Map')
self.writeLink(Path.joinPath(apiDocDir, self.attributeMapFile), 'Attribute Map')
self.writeVerticalBar()
if special == 'Method Map':
self.writeStyleString('Method Map', _class='underover')
else:
self.writeLink(Path.joinPath(apiDocDir, self.methodMapFile), 'Method Map')
self.writeVerticalBar()
self.writeLink("javascript:wopn('%s/%s.%s')" % (apiFileDir, self.helpPrefix, self.fileSuffix), 'Help')
self.writeVerticalBar()
if special == 'License':
self.writeStyleString('License', _class='underover')
else:
self.writeLink("javascript:wopn('%s/%s.%s')" % (apiFileDir, self.licensePrefix, self.fileSuffix), 'License')
self.writeEndCell()
self.writeEndRow()
self.writeStartRow(valign='top')
self.writeStartCell(align='center', valign='bottom')
if elem.container is None:
# root package
if special in ('Class Map', 'Attribute Map'):
self.writeLink(Path.joinPath(topPath, self.topDocDir, self.topApiFile), 'Home')
else:
self.writeStyleString('Home', _class='underover')
self.writeVerticalBar()
self.write('Package')
self.writeVerticalBar()
self.write('Class')
self.writeVerticalBar()
self.write('Attribute')
self.writeVerticalBar()
self.write('Method')
elif isinstance(elem,MetaModel.MetaPackage):
self.writeLink(Path.joinPath(topPath, self.topDocDir, self.topApiFile), 'Home')
self.writeVerticalBar()
self.writeStyleString('Package:', _class='underover')
self.writePrevNextLinks(topDocPath, prev, foll)
self.writeVerticalBar()
self.write('Class')
self.writeVerticalBar()
self.write('Attribute')
self.writeVerticalBar()
self.write('Method')
elif isinstance(elem,MetaModel.AbstractDataType):
self.writeLink(Path.joinPath(topPath, self.topDocDir, self.topApiFile), 'Home')
self.writeVerticalBar()
self.writeLink(Path.joinPath(topPath,self.fileFromTop(elem.container)), 'Package')
self.writeVerticalBar()
self.writeStyleString('Class:', _class='underover')
self.writePrevNextLinks(topDocPath, prev, foll)
self.writeVerticalBar()
self.write('Attribute')
self.writeVerticalBar()
self.write('Method')
elif isinstance(elem,MetaModel.MetaOperation):
self.writeLink(Path.joinPath(topPath, self.topDocDir, self.topApiFile), 'Home')
self.writeVerticalBar()
self.writeLink(Path.joinPath(topPath,self.fileFromTop(elem.container.container)), 'Package')
self.writeVerticalBar()
self.writeLink(Path.joinPath(topDocPath,self.fileFromTop(elem.container)), 'Class')
self.writeVerticalBar()
self.write('Attribute')
self.writeVerticalBar()
self.writeStyleString('Method:', _class='underover')
self.writePrevNextLinks(topPath, prev, foll)
else:
# attribute or role
self.writeLink(Path.joinPath(topPath, self.topDocDir, self.topApiFile), 'Home')
self.writeVerticalBar()
self.writeLink(Path.joinPath(topPath,self.fileFromTop(elem.container.container)), 'Package')
self.writeVerticalBar()
self.writeLink(Path.joinPath(topPath,self.fileFromTop(elem.container)), 'Class')
self.writeVerticalBar()
self.writeStyleString('Attribute:', _class='underover')
self.writePrevNextLinks(topDocPath, prev, foll)
self.writeVerticalBar()
self.write('Method')
self.writeEndCell()
self.writeEndRow()
self.writeStartRow()
self.writeCell()
self.writeEndRow()
self.writeEndTable()
self.writeEndDiv()
self.writeComment('TOP BANNER END')
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
###########################################################################
###########################################################################
[docs] def writeDiagramNavigatorBar(self, package = None, special = None):
"""write javastyle navigator bar for diagrams
"""
self.writeCommonNavigatorBar(package, isDiagram=True)
if package:
topPath = self.pathToTop(package, upDir=2)
else:
topPath = self.upDir(2) # HACK for Help and License
self.writeStartRow()
self.writeStartCell(align='center')
self.writeLink(Path.joinPath(topPath, self.topDocDir, self.topApiFile), 'API Home')
self.writeVerticalBar()
self.writeLink(Path.joinPath(topPath, self.topDocDir, self.classMapFile), 'Class Map')
apiFileDir = Path.joinPath(topPath, self.baseDirName, self.apiFileDir)
self.writeVerticalBar()
# tt = Path.joinPath(topPath, self.modelDiagramDir)
if special == 'Help':
self.writeStyleString('Help', _class='underover')
else:
self.writeLink('%s/%s.%s' % (apiFileDir, self.helpPrefix, self.fileSuffix), 'Help')
# self.writeLink('%s/%s.%s' % (tt, self.helpPrefix, self.fileSuffix), 'Help')
self.writeVerticalBar()
if special == 'License':
self.writeStyleString('License', _class='underover')
else:
self.writeLink('%s/%s.%s' % (apiFileDir, self.licensePrefix, self.fileSuffix), 'License')
# self.writeLink('%s/%s.%s' % (tt, self.licensePrefix, self.fileSuffix), 'License')
self.writeEndCell()
self.writeEndRow()
self.writeStartRow()
self.writeCell()
self.writeEndRow()
self.writeEndTable()
self.writeEndDiv()
self.writeComment('TOP BANNER END')
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
###########################################################################
###########################################################################
###def writeCommonNavigatorBar(self, elem = None, isDiagram = False, upDir = 0):
[docs] def writeCommonNavigatorBar(self, elem=None, isDiagram=False):
## upDir is hack to get Attribute Map pages to work
if elem:
##topPath = self.pathToTop(elem, isDiagram=isDiagram, upDir=upDir)
# topPath = self.pathToTop(elem, isDiagram=isDiagram, upDir=2)
topPath = self.pathToTop(elem, upDir=2)
# elif isDiagram:
# topPath = self.upDir(1)
else:
topPath = self.upDir(2) # HACK for Help and License
dataModelVersion = self.modelPortal.dataModelVersion
self.writeStartTable(height=100, width='100%', bgcolor=self.color1, border=0)
self.writeStartRow()
self.writeStartCell()
src = '%s/CCPN_Logo_200_x.gif'% Path.joinPath(topPath,self.imageDir)
ss = self.getImageString(src=src, id='toplink', border=0, alt='CCPN')
self.writeLink('http://www.ccpn.ac.uk/', ss, _class='mainlogo')
self.writeBreak()
self.writeNonBreakingSpaces(3)
self.write('Data Model version %s' % dataModelVersion)
self.writeEndCell()
tt = Path.joinPath(topPath, self.baseDirName, self.apiFileDir)
self.writeStartCell(width='80%', valign='center')
self.writeComment('TOP BANNER BEGIN')
self.writeStartDiv(_class='topbanner')
self.writeStartTable(width='100%', border=0)
self.writeStartRow(valign='top')
self.writeStartCell(width='80%', align='right')
self.writeLink("javascript:wopn('%s/acknowledgements.html')" % tt, 'Acknowledgements')
self.writeEndCell()
self.writeEndRow()
###########################################################################
###########################################################################
[docs] def writeAttributeTable(self, clazz, kind):
if kind == 'attrs':
anchor = 'Attributes'
elems = clazz.getAllAttributes()
else:
anchor = 'Link Attributes'
elems = clazz.getAllRoles()
if clazz.container == self.impPackage:
# only list details for those in same class
title = anchor
oneelems = [ e for e in elems if e.container == clazz ]
inhelems = [ e for e in elems if e.container != clazz ]
else:
# only list details for those in same package
title = anchor + ' (in package)'
# note: these names not appropriate in this context
oneelems = [ e for e in elems if e.container.container == clazz.container ]
inhelems = [ e for e in elems if e.container.container != clazz.container ]
oneelems = metaUtil.sortByAttribute(oneelems, 'name')
inhelems = metaUtil.sortByAttribute(inhelems, 'name')
self.writeHorizontalLine()
self.writeStartSection(cellpadding=5, width="100%")
# title
self.writeStartTable(cellpadding=2, cellspacing=2, width='100%')
self.writeStartRow(valign='center')
self.writeStartCell()
self.writeAnchorLink(anchor)
self.writeHeading(title, level=3)
self.writeEndCell()
tt = 'Go%sto%sTop' % (self.getNonBreakingSpaces(), self.getNonBreakingSpaces())
self.writeStartCell(align='right')
self.writeLink('#toplink', self.getStyleString(tt, style='font-size:9pt'))
self.writeEndCell()
self.writeEndRow()
self.writeEndTable()
# direct attributes
if oneelems:
self.writeStartTable(cellpadding=2, cellspacing=2, _class='elemtable')
self.writeStartRow()
self.writeCell('Attribute', align='left', _class='tblhead')
self.writeCell('Type', align='left', _class='tblhead')
self.writeCell('Multiplicity', align='left', _class='tblhead')
self.writeCell('Description', align='left', _class='tblhead')
self.writeEndRow()
for ee in oneelems:
if ee.isDerived:
ss = self.getEmphasisString('Derived.%s' % self.getNonBreakingSpaces())
elif (isinstance(ee,MetaModel.MetaRole)
and ee.hierarchy == metaConstants.parent_hierarchy):
ss = self.getEmphasisString('(Parent link).%s' % self.getNonBreakingSpaces())
elif (isinstance(ee,MetaModel.MetaRole)
and ee.hierarchy == metaConstants.child_hierarchy):
ss = self.getEmphasisString('(Child link).%s' % self.getNonBreakingSpaces())
else:
ss = ''
ss = ss + ee.documentation + ' ' + self.getNonBreakingSpaces()
(name, ref) = self.getLinkInfo(clazz, ee)
self.writeStartRow(valign='top')
self.writeCell(self.getLinkString('%s.%s' % (ref, self.fileSuffix), ee.name), _class='tblrow')
self.writeCell(self.getElemTypeString(ee), _class='tblrow')
self.writeCell(self.getMultiplicity(ee), _class='tblrow', align='center')
self.writeCell(ss, _class='tblrow')
self.writeEndRow()
self.writeEndTable()
else:
# no own elements. Make empty table
self.writeStartTable()
self.writeStartRow()
self.writeCell('None', valign='top')
self.writeEndRow()
self.writeEndTable()
# handle inherited elements
self.writeBreak()
if clazz.container == self.impPackage:
ss = ''
else:
ss = ' (not in package)'
self.writeStrongString('Inherited Attributes%s: ' % ss)
if inhelems:
ll = []
for ee in inhelems:
(name, ref) = self.getLinkInfo(clazz, ee)
ll.append(self.getLinkString('%s.%s' % (ref, self.fileSuffix), ee.name))
tt = ',' + self.getNonBreakingSpaces() + '\n'
self.write(tt.join(ll))
else:
self.write('None')
self.writeBreak()
self.writeEndSection()
###########################################################################
###########################################################################
[docs] def getClassAttrMethods(self, complexDataType, methods):
attrMethods = [ method for method in methods if method.opType in attrOpTypes \
and isinstance(method.target, MetaModel.MetaAttribute) ]
self.sortAttrMethods(attrMethods)
return attrMethods
###########################################################################
###########################################################################
[docs] def getClassLinkAttrMethods(self, complexDataType, methods):
if isinstance(complexDataType, MetaModel.MetaClass):
linkAttrMethods = [ method for method in methods if method.opType in attrOpTypes \
and isinstance(method.target, MetaModel.MetaRole) ]
self.sortAttrMethods(linkAttrMethods)
else:
linkAttrMethods = []
return linkAttrMethods
###########################################################################
###########################################################################
[docs] def getClassClassMethods(self, complexDataType, methods):
classMethods = [ method for method in methods if method.opType in classOpTypes ]
self.sortClassMethods(classMethods)
return classMethods
###########################################################################
###########################################################################
[docs] def getClassNewMethods(self, complexDataType, methods):
if isinstance(complexDataType, MetaModel.MetaClass):
newMethods = [ method for method in methods if method.opType in newOpTypes ]
newMethods = metaUtil.sortByAttribute(newMethods, 'name')
else:
newMethods = []
return newMethods
###########################################################################
###########################################################################
[docs] def getClassOtherMethods(self, complexDataType, methods):
otherMethods = [ method for method in methods if method.opType in otherOpTypes ]
otherMethods = metaUtil.sortByAttribute(otherMethods, 'name')
return otherMethods
###########################################################################
###########################################################################
[docs] def writeMethodTables(self, complexDataType):
package = complexDataType.container
if package == self.impPackage:
methods = complexDataType.operations
methodString = 'class'
else:
methods = complexDataType.getAllOperations()
methods = [ method for method in methods if method.container.container == package ]
methodString = 'package'
toplinkString = 'Go%sto%sTop' % (self.getNonBreakingSpaces(), self.getNonBreakingSpaces())
toplinkString = self.getLinkString('#toplink', self.getStyleString(toplinkString, style='font-size:9pt'))
nonStdString = self.getStrongString('non-std.')
classString = self.getStrongString('static')
ll = self.getClassPageMethods(complexDataType, methods)
ncols = 2
for (kind, methods) in ll:
haveAttrCol = kind.endswith('Attribute')
haveCommCol = (kind != 'Factory')
if haveAttrCol:
ncols += 2
if haveCommCol:
ncols += 1
self.writeHorizontalLine()
self.writeStartSection(cellpadding=5, width="100%")
self.writeAnchorLink('%s Methods' % kind)
self.writeHeading('%s Methods (in %s)' % (kind, methodString), level=3)
self.writeStartTable(cellpadding=2, cellspacing=2, width='100%')
self.writeStartRow(valign='center')
self.writeCell(toplinkString, align='right')
self.writeEndRow()
self.writeEndTable()
self.writeStartTable(cellpadding=2, cellspacing=2, _class='elemtable')
self.writeStartRow()
if haveAttrCol:
self.writeCell('Attribute', align='left', _class='tblhead')
self.writeCell('Method', align='left', _class='tblhead')
self.writeCell('Return', align='left', _class='tblhead')
self.writeCell('Parameters', align='left', _class='tblhead')
if haveCommCol:
self.writeCell('Comment', align='left', _class='tblhead')
self.writeEndRow()
if methods:
target = None
for n in range(len(methods)):
method = methods[n]
self.writeStartRow(valign='top')
# Attribute
if haveAttrCol:
if method.target != target:
attr = method.target
(name, ref) = self.getLinkInfo(attr.container, attr)
ss = self.getLinkString('%s.%s' % (ref, self.fileSuffix), attr.name)
self.writeCell(ss, _class='tblspecialrow', colspan=ncols)
self.writeEndRow()
self.writeStartRow(valign='top')
# Method
if haveAttrCol:
colspan = 2
align = 'right'
else:
colspan = 1
align = 'left'
if self.methodHasOwnPage(method):
(name, ref) = self.getLinkInfo(complexDataType, method)
###ss = self.getLinkString('%s.%s' % (ref, self.fileSuffix), method.name)
ss = self.getLinkString('%s.%s' % (ref, self.fileSuffix), self.getFuncname(method))
else:
###ss = method.name
ss = self.getFuncname(method)
self.writeCell(ss, _class='tblrow', align=align, colspan=colspan)
# Return
self.writeCell(self.getMethodReturn(method), _class='tblrow')
# Parameters
self.writeCell(self.getMethodParameters(method), _class='tblrow')
# Comment
if haveCommCol:
ll = []
if method.scope == metaConstants.classifier_level:
ll.append(classString)
if not method.isImplicit:
ll.append(nonStdString)
if kind == 'Other':
ll.append(self.getElemDocString(method))
ss = self.getNonBreakingSpaces()
ss = ss.join(ll)
self.writeCell(ss, _class='tblrow')
target = method.target
self.writeEndRow()
else:
self.writeStartRow(valign='top')
self.writeCell('None')
self.writeEndRow()
self.writeEndTable()
self.writeEndSection()
###########################################################################
###########################################################################
[docs] def writeDiagramDocumentation(self, package):
if not package.container:
self.writeRootPackageDiagram(package)
elif package.containedPackages:
self.writeBranchPackageDiagram(package)
else:
self.writeLeafPackageDiagram(package)
###########################################################################
###########################################################################
[docs] def writeInheritanceDiagram(self, complexDataType):
spaceImage = 'whiteBlank.gif'
vertLine = 'vertLine.gif'
horizLine = 'horizLine.gif'
cornerLine = 'cornerLine.gif'
# get superclasses
supers = [[complexDataType]]
supertypes = complexDataType.supertypes
while supertypes:
supers.append(supertypes)
supertypes = supertypes[0].supertypes
# image dir
imgPath = Path.joinPath(self.pathToTop(complexDataType, upDir=2), self.imageDir)
src = '%s/%s' % (imgPath, spaceImage)
space = self.getImageString(src=src, align='top', border=0)
# build diagram
self.writeHeading('Inheritance:', level=3)
self.writeStartIndent()
indent = ''
supertypes = supers.pop()
while True:
ll = []
for supertype in supertypes:
(name, ref) = self.getLinkInfo (complexDataType, supertype)
link = Path.joinPath(ref, self.indexFile)
ss = self.getLinkString(link, self.getImportName(supertype))
ll.append(ss)
cc = ' ' + self.getNonBreakingSpaces()
self.write(cc.join(ll))
self.writeBreak()
if not supers:
break
tt = indent
for xx in (vertLine, cornerLine, horizLine, horizLine):
tt = tt + self.getImageString(src='%s/%s' % (imgPath, xx), align='top', border=0)
if xx == vertLine:
tt = tt + self.getBreakString() + indent
self.write(tt)
indent += space * 3
supertypes = supers.pop()
self.writeEndIndent()
###########################################################################
###########################################################################
[docs] def writePrevNextLinks(self, topPath, prev, foll):
strs = []
for tag,xx in (('prev',prev), ('foll',foll)):
if xx is None:
strs.append(tag)
else:
link = Path.joinPath(topPath, self.fileFromTop(xx))
strs.append(self.getLinkString(link, tag))
self.write('{')
self.write(strs[0])
self.writeVerticalBar()
self.write(strs[1])
self.write('}')
###########################################################################
###########################################################################
###########################################################################
###########################################################################
###def writeElementHeader(self, elem, title, prev=None, foll=None, special = None, upDir = 0, attributeLetter = 'A'):
###########################################################################
###########################################################################
###########################################################################
###########################################################################
###########################################################################
###########################################################################
###########################################################################
###########################################################################
[docs] def writePageHeading(self, elem, title):
name = elem.name
self.writeHeading('%s: %s' % (title, name), level=2)
qname = self.getImportName(elem)
ss = qname[:-(len(name)+1)]
if isinstance(elem.container, MetaModel.MetaPackage):
fromstr = 'Package'
if elem.container is elem.topPackage():
ss = 'Root'
# TBD: not sure this works for all implementations
addr = '../../../%s/%s' % (self.topDocDir, self.topApiFile)
elif self.elemHasOwnDirectory(elem):
addr = '../%s' % self.indexFile
else:
addr = self.indexFile
else:
fromstr = 'Class'
addr = self.indexFile
self.writeStartIndent()
heading = 'from %s %s' % (fromstr, self.getLinkString(addr, ss))
self.writeHeading(heading, level=3)
self.writeEndIndent()
###########################################################################
###########################################################################
[docs] def sortAttrMethods(self, methods):
methods.sort(key=lambda method:(method.target.name, method.opType))
###########################################################################
###########################################################################
[docs] def sortClassMethods(self, methods):
methods.sort(key=lambda method:method.opType)
###########################################################################
###########################################################################
[docs] def methodHasOwnPage(self, method):
return method.codeStubs.get(self.handCodeKey)
###########################################################################
###########################################################################
[docs] def getMethodReturn(self, method):
returnPars = [ parameter for parameter in method.parameters if parameter.direction == metaConstants.return_direction ]
n = len(returnPars)
assert n in (0, 1), 'method %s has %d return parameters, should be 0 or 1' % (method.qualifiedName(), n)
if n == 0:
returnString = ''
else:
param = returnPars[0]
returnString = self.getParamString(param)
return returnString
###########################################################################
###########################################################################
[docs] def getMethodParameters(self, method):
if method.opType == 'new' and not method.opSubType:
paramsString = self.getNewParamString(method)
elif method.opType in ('findFirst', 'findAll') and not method.opSubType:
paramsString = self.getKeywordValueString(method)
else:
params = [parameter for parameter in method.parameters
if parameter.direction != metaConstants.return_direction]
ll = []
for param in params:
paramString = self.getParamString(param)
ll.append(paramString)
if ll:
paramsString = ', '.join(ll)
else:
paramsString = '-'
return paramsString
###########################################################################
###########################################################################
[docs] def determineAllAbstractDataTypes(self, package, allAbstractDataTypes):
if package.containedPackages:
for pp in package.containedPackages:
self.determineAllAbstractDataTypes(pp, allAbstractDataTypes)
else:
allAbstractDataTypes.extend(package.classes)
allAbstractDataTypes.extend(package.dataTypes)
allAbstractDataTypes.extend(package.dataObjTypes)
###########################################################################
###########################################################################
[docs] def determineAllAttrRoles(self, package, allAttrRoles):
if package.containedPackages:
for pp in package.containedPackages:
self.determineAllAttrRoles(pp, allAttrRoles)
else:
for clazz in package.classes:
allAttrRoles.extend(clazz.attributes)
allAttrRoles.extend(clazz.roles)
for dataObjType in package.dataObjTypes:
allAttrRoles.extend(dataObjType.attributes)
###########################################################################
###########################################################################
[docs] def determineAllMethods(self, package, allMethods):
if package.containedPackages:
for pp in package.containedPackages:
self.determineAllMethods(pp, allMethods)
else:
for clazz in package.classes:
for op in clazz.operations:
if not op.opSubType and not op.name.startswith('_'):
allMethods.append(op)
###########################################################################
###########################################################################
[docs] def getPrevNextPackages(self, package):
if package.container:
containedPackages = metaUtil.sortByAttribute(package.container.containedPackages, 'name')
m = containedPackages.index(package)
if m > 0:
prev = containedPackages[m-1]
else:
prev = None
if m < len(containedPackages)-1:
foll = containedPackages[m+1]
else:
foll = None
else:
prev = foll = None
return (prev, foll)
###########################################################################
###########################################################################
[docs] def getElemDocString(self, elem):
doc = self.normaliseString(elem.documentation)
if elem.taggedValues.get('isDraft'):
doc = self.draftDocString + doc
return doc
###########################################################################
###########################################################################
[docs] def getLinkInfo(self, fromElem, toElem):
"""return tuple of relName, relDirectory.
see code for details
"""
if toElem.container is None:
raise MemopsError('getLinkInfo callled with containerless element %s' % toElem)
# logic moved to bottom because path was not always coming out correctly
###elif (fromElem.container is toElem.container and toElem.container.container is not None):
### # elements with the same container are in the same directory,
### # unless they are packages contained in RootPackage
### return (toElem.name, '../%s' % toElem.name)
else:
path = Path.joinPath(self.pathToTop(fromElem), self.directoryFromTop(toElem, ignoreElemType=True))
if isinstance(toElem,MetaModel.MetaDataType) or isinstance(toElem, MetaModel.MetaDataObjType):
pp = toElem.container
if pp == self.impPackage:
return toElem.name, path
if fromElem.container is toElem.container and toElem.container.container is not None:
name = toElem.name
else:
name = self.getImportName(toElem, fromElem)
return name, path
###########################################################################
###########################################################################
[docs] def pathToTop(self, element, isDiagram=False, upDir=0):
""" return relative directory path from a given element to the top directory
"""
length = len(self.getElementPathList(element)) + upDir
if element.container is None:
if hasattr(element, 'topPackage') and element is element.topPackage():
# this is the root package
length = upDir
else:
raise MemopsError("path from root element not implemented for %s"
% element
)
elif isDiagram:
if element.containedPackages:
length += 1
elif not self.elemHasOwnDirectory(element):
length -= 1
return self.upDir(length)
###########################################################################
###########################################################################
[docs] def getElementPathList(self, element):
return element.qualifiedName().split('.')
###########################################################################
###########################################################################
[docs] def upDir(self, n = 1):
if n == 0:
return ''
else:
return Path.joinPath(*(n * ['..']))
###########################################################################
###########################################################################
# TBD: not sure why ignoreElemType comes into use in one case
# something probably wrong with that use, look at again
[docs] def directoryFromTop(self, element, ignoreElemType = False):
""" Generate directory name relative to top directory of an element
"""
#n = len(self.baseDirNames)
# ll = self.baseDirNames + element.qualifiedName().split('.')
ll = element.qualifiedName().split('.')
#ll[n+1:n+1] = self.docSubDirs
if not ignoreElemType and not self.elemHasOwnDirectory(element):
del ll[-1]
return Path.joinPath(*ll)
###########################################################################
###########################################################################
[docs] def fileFromTop(self, element):
directory = self.directoryFromTop(element)
if self.elemHasOwnDirectory(element):
fileName = Path.joinPath(directory, self.indexFile)
else:
fileName = '%s.%s' % (Path.joinPath(directory, element.name), self.fileSuffix)
return fileName
###########################################################################
###########################################################################
[docs] def getObjDocDirName(self, metaObj):
fileName = self.getObjDocFileName(metaObj)
dirName = Path.splitPath(fileName)[0]
return dirName
###########################################################################
###########################################################################
[docs] def getObjDocFileName(self, metaObj, absoluteName=True, addSuffix=False):
""" Get filename for metaObj
If absoluteName is True the file name is absolute
otherwise it is relative to the relevant baseDir
"""
# absolute or relative path
if absoluteName:
#pathList = [self.rootDirName] + self.baseDirNames
pathList = [self.rootDirName, self.topDocDir]
else:
pathList = []
if metaObj.container is None:
# Root package only
pathList.append(metaConstants.modellingPackageName)
#pathList.append(self.codeDirName)
#pathList.append(self.docDir)
pathList.append(self.rootFileName)
else:
# any other object
ll = metaObj.qualifiedName().split('.')
#ll[1:1] = [self.codeDirName, self.docDir]
pathList.extend(ll)
if self.elemHasOwnDirectory(metaObj):
# gets own directory
pathList.append(self.indexPrefix)
# add suffix
if addSuffix and self.fileSuffix:
pathList[-1] = '%s.%s' % (pathList[-1], self.fileSuffix)
#
return Path.joinPath(*pathList)
###########################################################################
###########################################################################
[docs] def getParentString(self, clazz):
""" get string with parent class name
"""
parentRole = clazz.parentRole
if parentRole:
otherClass = parentRole.valueType
return 'link %s to class %s' % (parentRole.name,
self.getEmphasisString(self.getElemTypeString(parentRole)))
else:
return 'None'
###########################################################################
###########################################################################
[docs] def getElemTypeString(self, elem):
""" get attribute type string (string or link) for HTML
"""
if isinstance(elem,MetaModel.MetaParameter):
target = elem.valueType
(name, ref) = self.getLinkInfo(elem.container.container,target)
elif isinstance(elem,MetaModel.MetaAttribute):
target = elem.valueType
(name, ref) = self.getLinkInfo(elem.container,target)
# TBD: is below correct (first clause added, second was there)???
if isinstance(target, MetaModel.MetaDataType) and target.name == target.typeCodes[self.typeCodeKey]:
name = target.name
elif isinstance(elem,MetaModel.MetaRole):
target = elem.valueType
(name, ref) = self.getLinkInfo(elem.container,target)
else:
raise MemopsError('getElemTypeString called with object of class %s' % elem.__class__.__name__)
if self.elemHasOwnDirectory(target):
return '<a href ="%s/%s.html">%s</a>' % (ref, ApiDocGen.indexPrefix, name)
else:
return '<a href ="%s.html">%s</a>' % (ref, name)
###########################################################################
###########################################################################
[docs] def getMultiplicity(self, obj):
""" get multiplicity string from object with a locard and hicard
"""
hicard = obj.hicard
if hicard == metaConstants.infinity:
hicard = '*'
return '%s..%s' % (obj.locard,hicard)
###########################################################################
###########################################################################
[docs] def getMandatoryElements(self, elem):
""" get list of mandatory element names
All elements with locard == hicard are mandatory
"""
hasOptionals = False
mandatories = []
for ee in elem.getAllAttributes():
if not ee.isDerived and not ee.isAutomatic and not ee.isImplementation:
if ee.locard > 0:
if not ee.defaultValue:
mandatories.append(ee.name)
else:
hasOptionals = True
if isinstance(elem, MetaModel.MetaClass):
for ee in elem.getAllRoles():
if (ee.hierarchy == metaConstants.no_hierarchy
and not ee.isDerived and not ee.isAutomatic and not ee.isImplementation):
if ee.locard > 0:
mandatories.append(ee.name)
else:
hasOptionals = True
return mandatories, hasOptionals
###########################################################################
###########################################################################
[docs] def elemHasOwnDirectory(self, elem):
""" whether element's HTML page is in own directory or in container's directory
"""
if isinstance(elem, MetaModel.MetaPackage) or isinstance(elem, MetaModel.MetaClass) or isinstance(elem, MetaModel.MetaDataObjType):
return True
else:
return False
###########################################################################
###########################################################################
[docs] def getDiagramOrderedPackages(self):
""" return packages ordered depth-first for use in left bar of diagram pages
"""
mp = self.modelPortal
topPackage = mp.topPackage
usePackages = mp.branchPackages() + mp.leafPackagesAlphabetic()
# traverse packages in depth-first order, adding to list if in usePackages
result = []
#stack = [metaUtil.sortByAttribute(topPackage.containedPackages, 'name')]
#stack.reverse()
stack = [[topPackage]]
while stack:
current = stack[-1].pop()
if not stack[-1]:
del stack[-1]
if current in usePackages:
result.append(current)
ll = metaUtil.sortByAttribute(current.containedPackages, 'name')
if ll:
ll.reverse()
stack.append(ll)
return result
###########################################################################
###########################################################################
[docs] def getElemMethods(self, elem):
""" return methods listed on attribute page
"""
opTypes = ('get', 'sorted', 'set', 'add', 'remove', 'new', 'findFirst', 'findAll')
ops = {}
for opType in opTypes:
ops[opType] = []
for op in elem.container.operations:
if op.name.startswith('__'):
pass
elif (op.target == elem or (isinstance(elem, MetaModel.MetaRole) and
elem.hierarchy == metaConstants.child_hierarchy and
op.target in elem.valueType.getNonAbstractSubtypes())):
ops[op.opType].append((op.name, op))
methods = []
for opType in opTypes:
ops[opType].sort()
methods.extend([op for (name, op) in ops[opType]])
return methods
###########################################################################
###########################################################################
[docs] def getClassPageMethods(self, complexDataType, method):
raise MemopsError('must be overridden in subclass')
###########################################################################
###########################################################################
[docs] def getParamString(self, parameter):
raise MemopsError('must be overridden in subclass')
###########################################################################
###########################################################################
[docs] def getKeywordValueString(self, method):
raise MemopsError('must be overridden in subclass')
###########################################################################
###########################################################################
[docs] def getNewParamString(self, method):
raise MemopsError('must be overridden in subclass')
###########################################################################
###########################################################################
[docs] def writeConstructorRows(self, clazz, mandatoryElements):
raise MemopsError('must be overridden in subclass')