Main Page | Packages | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | Related Pages

rcTestReport.py

00001 #!/usr/local/bin/python
00002 #
00003 #                               Copyright 2002
00004 #                                     by
00005 #                        The Board of Trustees of the
00006 #                     Leland Stanford Junior University.
00007 #                            All rights reserved.
00008 #
00009 
00010 __facility__ = "Online"
00011 __abstract__ = "Test report generator class for RunControl"
00012 __author__   = "S. Tuvi <stuvi@SLAC.Stanford.edu> SLAC - GLAST LAT I&T/Online"
00013 __date__     = ("$Date: 2005/08/31 20:58:05 $").split(' ')[1]
00014 __version__  = "$Revision: 2.5 $"
00015 __release__  = "$Name: R04-12-00 $"
00016 __credits__  = "SLAC"
00017 
00018 import LATTE.copyright_SLAC
00019 
00020 import                         Pyana
00021 from xml.dom             import Node
00022 #from xml.dom            import implementation
00023 #from xml.dom.ext        import PrettyPrint
00024 #from xml.dom.ext.reader import Sax2
00025 #from xml.dom.minidom    import getDOMImplementation, parseString, Node
00026 from Ft.Xml.Domlette     import NonvalidatingReader, PrettyPrint, implementation
00027 
00028 from LATTE.database.gSchemaConfig import LAT_NAMESPACE
00029 
00030 from cStringIO           import StringIO
00031 
00032 class rcTestReport(object):
00033   """\brief Test Report class for RunControl.
00034 
00035   This class provides a mechanism to create test reports in a well formed (XML) format using
00036   the provided report building methods and lets the user transform it to HTML format by providing
00037   an XSLT stylesheet template. A third-party tool called Pyana is used to do the transformation.
00038   A sample template (reportStyle.xsl.sample) is provided in the RunControl directory. For more
00039   information on XSLT see the following links:
00040 
00041   <p><a href="http://www.w3.org/TR/xslt">XSL Transformations W3C Recommendation</a></p>
00042   <p><a href="http://www.xfront.com/xsl.html">XSLT Tutorial</a></p>
00043 
00044   """
00045 
00046   def __init__(self):
00047     self.__reports = []
00048 
00049   def initReport(self, title):
00050     """ Initializes the report class and provides a title for the report
00051 
00052     \param title The title that will show in the window title of the HTML browser
00053     """
00054     #self.__doc = implementation.createDocument(None,None,None)
00055     #self.__doc = getDOMImplementation().createDocument(None,None,None)
00056     self.__doc = implementation.createDocument(None,None,None)
00057     self.__root = self.__doc.createElementNS(LAT_NAMESPACE, "TestReport")
00058     self.__doc.appendChild(self.__root)
00059     titleNode = self.__doc.createElementNS(LAT_NAMESPACE, "Title")
00060     data = self.__doc.createTextNode(title)
00061     titleNode.appendChild(data)
00062     self.__root.appendChild(titleNode)
00063     self.__maxHeadingLine = 0
00064     self.__maxSectionId = 0
00065     self.__maxTableId = 0
00066     self.__sectionNodes = {}
00067     self.__tableNodes = {}
00068 
00069   def addHTML(self, htmlString, section=None):
00070     """ Adds an arbitrary HTML fragment to the end of the report or a section
00071 
00072     \param htmlString HTML fragment.
00073     \param section    Optional section id that this HTML will be written to.
00074                       If no section is specified then HTML is added to the
00075                       end of the report.
00076     """
00077     htmlDom = self.__createHTMLDom(htmlString)
00078     if section is None:
00079       self.__root.appendChild(htmlDom)
00080     else:
00081       sectionNode = self.__sectionNodes[section]
00082       sectionNode.appendChild(htmlDom)
00083 
00084   def addHeading(self, text):
00085     """ Adds a heading to the report
00086 
00087     \param text Heading text
00088     """
00089     heading = self.findTag(self.__root, 'Heading')
00090     if heading is None:
00091       heading = self.__doc.createElementNS(LAT_NAMESPACE, 'Heading')
00092       self.__root.appendChild(heading)
00093     self.__maxHeadingLine += 1
00094     line = self.__doc.createElementNS(LAT_NAMESPACE, 'Line')
00095     line.setAttributeNS(LAT_NAMESPACE, 'no', str(self.__maxHeadingLine))
00096     line.appendChild(self.__createHTMLDom(text))
00097     heading.appendChild(line)
00098 
00099   def addSection(self, caption, insert=1):
00100     """ Adds a section to the report and returns the section id.
00101 
00102     \param  caption Section caption
00103     \param  insert 0 = Do not insert the section into the report
00104                    1 = Insert the section into the report (default)
00105     \return Section id.
00106     """
00107     self.__maxSectionId += 1
00108     sectionNode = self.__doc.createElementNS(LAT_NAMESPACE, 'Section')
00109     sectionNode.setAttributeNS(LAT_NAMESPACE, 'id', str(self.__maxSectionId))
00110     sectionNode.appendChild(self.__createHTMLNode('Caption',caption))
00111 
00112     if insert == 1:
00113       self.__root.appendChild(sectionNode)
00114     self.__sectionNodes[self.__maxSectionId] = sectionNode
00115     return self.__maxSectionId
00116 
00117   def insertSection(self, sectionId, beforeSectionId=None):
00118     """ Inserts a previously added section (with insert=0)
00119     to the specified position in the report.
00120 
00121     \param sectionId       Id of the section to be inserted
00122     \param beforeSectionId Id of the section that will come after the section specified
00123                            by \a sectionId. If it is None then it is appended to the end.
00124                            Defaults to None.
00125     """
00126     if beforeSectionId is not None:
00127       self.__root.insertBefore(self.__sectionNodes[sectionId], self.__sectionNodes[beforeSectionId])
00128     else:
00129       self.__root.appendChild(self.__sectionNodes[sectionId])
00130 
00131   def addSectionItem(self, sectionId, label, text, url=''):
00132     """ Adds a section item.
00133     Section items are entries with a label and text and an optional URL.
00134 
00135     \param sectionId Id of the section that this item will be inserted in.
00136     \param label     Item label
00137     \param text      Item text
00138     \param url       Item URL
00139     """
00140     sectionNode = self.__sectionNodes[sectionId]
00141     itemNode = self.__doc.createElementNS(LAT_NAMESPACE, 'Item')
00142     itemNode.appendChild(self.__createHTMLNode('Label',label))
00143     itemNode.appendChild(self.__createHTMLNode('Text',text))
00144     if (url != '') & (url != None):
00145       linkNode = self.__doc.createElementNS(LAT_NAMESPACE, 'Link')
00146       data = self.__doc.createTextNode(url)
00147       linkNode.appendChild(data)
00148       itemNode.appendChild(linkNode)
00149     sectionNode.appendChild(itemNode)
00150 
00151   def addSectionImage(self, sectionId, caption, url, width='', height=''):
00152     """ Adds an image to a section. Images can have a caption,
00153     and an optional width and height. The url parameter specifies the
00154     location of the image.
00155 
00156     \param sectionId Id of the section that this image will be inserted in.
00157     \param caption   Image caption
00158     \param url       Image source URL
00159     \param width     Optional width of the image
00160     \param height    Optional height of the image
00161     """
00162     sectionNode = self.__sectionNodes[sectionId]
00163     imageNode = self.__doc.createElementNS(LAT_NAMESPACE, 'Image')
00164     imageNode.appendChild(self.__createHTMLNode('Caption',caption))
00165     linkNode = self.__doc.createElementNS(LAT_NAMESPACE, 'Link')
00166     data = self.__doc.createTextNode(url)
00167     linkNode.appendChild(data)
00168     imageNode.appendChild(linkNode)
00169     if width != '':
00170       widthNode = self.__doc.createElementNS(LAT_NAMESPACE, 'Width')
00171       data = self.__doc.createTextNode(str(width))
00172       widthNode.appendChild(data)
00173       imageNode.appendChild(widthNode)
00174     if height != '':
00175       heightNode = self.__doc.createElementNS(LAT_NAMESPACE, 'Height')
00176       data = self.__doc.createTextNode(str(height))
00177       heightNode.appendChild(data)
00178       imageNode.appendChild(heightNode)
00179     sectionNode.appendChild(imageNode)
00180 
00181 
00182   def addSectionTable(self, sectionId, border='1', width=''):
00183     """ Adds a table to a section. Border and width are optional
00184 
00185     \param sectionId Id of the section that this image will be inserted in.
00186     \param border    Specifies whether the table will have a border or not. Default value is 1.
00187     \param width     Specifies the width of the border in percentage relative to the width of the page.
00188 
00189     \return          Table id.
00190     """
00191     self.__maxTableId += 1
00192     sectionNode = self.__sectionNodes[sectionId]
00193     tableNode = self.__doc.createElementNS(LAT_NAMESPACE, 'Table')
00194     if border != '':
00195       tableNode.setAttributeNS(LAT_NAMESPACE, 'border', border)
00196     if width != '':
00197       tableNode.setAttributeNS(LAT_NAMESPACE, 'width', width)
00198     sectionNode.appendChild(tableNode)
00199     self.__tableNodes[self.__maxTableId] = tableNode
00200     return self.__maxTableId
00201 
00202   def addTableHeader(self, tableId, text, align=''):
00203     """ Adds one column header to the table.
00204 
00205     \param tableId Id of the table where column headers are being added.
00206     \param text    Column header text.
00207     \param align   Optional text alignment.
00208     """
00209     tableNode = self.__tableNodes[tableId]
00210     tr = self.findTag(tableNode, 'TR')
00211     if tr is None:
00212       tr = self.__doc.createElementNS(LAT_NAMESPACE, 'TR')
00213       tableNode.appendChild(tr)
00214     th = self.__doc.createElementNS(LAT_NAMESPACE, 'TH')
00215     if align != '':
00216       th.setAttributeNS(LAT_NAMESPACE, 'align', align)
00217     #data = self.__doc.createTextNode(text)
00218     #th.appendChild(data)
00219     th.appendChild(self.__createHTMLDom(text))
00220     tr.appendChild(th)
00221 
00222   def beginTableRow(self, tableId):
00223     """ Starts a table row.
00224 
00225     \param tableId Id of the table where the row is being added.
00226     """
00227     tableNode = self.__tableNodes[tableId]
00228     tr = self.__doc.createElementNS(LAT_NAMESPACE, 'TR')
00229     tableNode.appendChild(tr)
00230     self.__currentTableRow = tr
00231 
00232   def addTableData(self, text, url='', align='', width=''):
00233     """ Adds a data column to the table row that was started by the last
00234     beginTableRow() call.
00235 
00236     \param text  Text of the data column.
00237     \param url   Optional. If the text refers to a hyperlink provide the URL here.
00238     \param align Optional text alignment.
00239     \param width Optional column width in percentage.
00240     """
00241     tr = self.__currentTableRow
00242     if tr is None:
00243       raise RuntimeError, "No current row"
00244     else:
00245       td = self.__doc.createElementNS(LAT_NAMESPACE, 'TD')
00246       if align != '':
00247         td.setAttributeNS(LAT_NAMESPACE, 'align', align)
00248       if width != '':
00249         td.setAttributeNS(LAT_NAMESPACE, 'width', align)
00250       if url != '':
00251         href = self.__doc.createElementNS(LAT_NAMESPACE, 'A')
00252         href.setAttributeNS(LAT_NAMESPACE, 'href',url)
00253       data = self.__createHTMLDom(str(text))
00254       if url != '':
00255         href.appendChild(data)
00256         data = href
00257       td.appendChild(data)
00258       tr.appendChild(td)
00259 
00260 
00261   def findTag(self, node, tagName):
00262     tNode = None
00263     for n in self.getChildNodes(node):
00264       if n.tagName == tagName:
00265         tNode = n
00266         break
00267     return tNode
00268 
00269   def xmlToString(self):
00270     xmlStr = StringIO()
00271     PrettyPrint(self.__doc, xmlStr)
00272     #self.__doc.writexml(xmlStr)
00273     return xmlStr.getvalue()
00274 
00275   def transformToFile(self, xslFileName, htmlFileName):
00276     """ Based on the input template and output filename parameters
00277     creates an HTML report.
00278 
00279     \param xslFileName  Input XSLT template file name.
00280     \param htmlFileName Output HTML filename.
00281     """
00282     xslFile = file(xslFileName)
00283     htmlFile = file(htmlFileName, 'w+')
00284     Pyana.transform2Writer(self.xmlToString(), xslFile, htmlFile)
00285     self.__reports.append(htmlFileName)
00286 
00287   def getReports(self):
00288     return self.__reports
00289 
00290   def getChildNodes(self, node):
00291     childNodes = []
00292     for n in node.childNodes:
00293       if (n.nodeType == Node.TEXT_NODE and \
00294           (n.data[0] == '\n' or n.data[0].strip() == '')) \
00295           or n.nodeType == Node.COMMENT_NODE:
00296         pass
00297       else:
00298         childNodes.append(n)
00299     return childNodes
00300 
00301 ##private
00302   def __createHTMLDom(self, text):
00303     return self.__createHTMLNode('cdatanode', text)
00304 
00305   def __createHTMLNode(self, nodeName, text):
00306     htmlString = '<'+nodeName+'>' + text + '</'+nodeName+'>'
00307     #htmlDoc = Sax2.FromXml(htmlString).documentElement
00308     htmlDoc = NonvalidatingReader.parseString(htmlString, 'urn:dummy').documentElement
00309     return self.__doc.importNode(htmlDoc,1)

Generated on Fri Jul 21 13:26:31 2006 for LATTE R04-12-00 by doxygen 1.4.3