# $Id: N3GenDocIssues.py,v 1.6 2002/11/26 17:42:03 graham Exp $ # # RDF document issues report generator # # Uses an RDF-based description stored in an N3Model to generate # document issue reports. # #--------+---------+---------+---------+---------+---------+---------+---------+ # # Copyright (c) 2002, G. KLYNE # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # #--------+---------+---------+---------+---------+---------+---------+---------+ # $Source: /file/cvsdev/PythonN3/N3GenDocIssues.py,v $ # $Author: graham $ # $Revision: 1.6 $ #--------+---------+---------+---------+---------+---------+---------+---------+ # 1 2 3 4 5 6 7 8 import os import sys import string import StringIO from N3Exception import N3Exception from N3Node import N3Node from N3Model import N3Model, N3PrefixError from N3Report import N3Report, N3ReportError #--------+---------+---------+---------+---------+---------+---------+---------+ # Define N3GenDocIssues package exception conditions # # Base class for exceptions # class N3GenDocIssuesError( N3Exception ): """ Base class for N3GenDocIssues generation errors. Attributes: message -- explanation of the error """ def __init__(self, message): N3Exception.__init__( self, "N3GenDocIssuesError: "+message ) pass class N3CommandError( N3GenDocIssuesError ): """ Invalid command line argument supplied Attributes: message -- explanation of the error """ def __init__(self, message): N3GenDocIssuesError.__init__( self, "N3CommandError: "+message ) pass class N3QueryError( N3GenDocIssuesError ): """ Error in query structure Attributes: message -- explanation of the error """ def __init__(self, message): N3GenDocIssuesError.__init__( self, "N3QueryError: "+message ) pass class N3ReadError( N3GenDocIssuesError ): """ Error reading data files Attributes: message -- explanation of the error """ def __init__(self, message, file): N3GenDocIssuesError.__init__( self, "N3ReadError: "+message ) self.File = file pass class N3GenerateError( N3GenDocIssuesError ): """ Error generating registry files Attributes: message -- explanation of the error """ def __init__(self, message): N3GenDocIssuesError.__init__( self, "N3GenerateError: "+message ) pass #--------+---------+---------+---------+---------+---------+---------+---------+ # N3GenDocIssues - message header registry generation functions # class N3GenDocIssues: #--------------------------------------------------------------------------- # Registry generation model data #--------------------------------------------------------------------------- RegDef = ''' @prefix rdf: . @prefix rdfs: . @prefix foaf: . @prefix rep: . @prefix dc: . @prefix iss: . @prefix irep: . irep:GenReport a rep:Report ; :- ( [ rep:cmd rep:if ; rep:defined "htmlname" ; rep:do irep:HTMLReport ] ) . irep:HTMLReport a rep:Report ; :- ( [ rep:cmd rep:open ; rep:chan "t" ; rep:file ( [ rep:var "path" ] "/" [ rep:var "htmlname" ] ) ] [ rep:cmd rep:if ; rep:pattern irep:ThisPattern ; rep:do ( [ rep:cmd rep:write ; rep:chan "t" ; rep:data irep:ThisHead ] [ rep:do irep:GenDocReport ] [ rep:cmd rep:write ; rep:chan "t" ; rep:data irep:ThisFoot ] ) ; rep:else ( [ rep:cmd rep:write ; rep:chan "t" ; rep:data irep:NoReport ] ) ] [ rep:cmd rep:close ; rep:chan "t" ] ) . irep:GenDocReport :- ( [ rep:cmd rep:for ; rep:pattern irep:DocPattern ; rep:do ( [ rep:cmd rep:write ; rep:chan "t" ; rep:data irep:DocHead1 ] [ rep:cmd rep:for ; rep:pattern irep:DocEditorPattern ; rep:do ( [ rep:cmd rep:write ; rep:chan "t" ; rep:data irep:DocEditor ] ) ] [ rep:cmd rep:write ; rep:chan "t" ; rep:data irep:DocHead2 ] [ rep:cmd rep:for ; rep:pattern irep:DocHistoryPattern ; rep:do ( [ rep:cmd rep:write ; rep:chan "t" ; rep:data irep:DocHistory ] ) ] [ rep:cmd rep:write ; rep:chan "t" ; rep:data irep:DocHead3 ] [ rep:cmd rep:for ; rep:pattern irep:IssuePattern ; rep:do ( [ rep:cmd rep:write ; rep:chan "t" ; rep:data irep:TableItem ] [ rep:cmd rep:if ; rep:defined "entries" ; rep:do ( [ rep:cmd rep:if ; rep:pattern irep:IssueDetailPattern ; rep:do ( [ rep:cmd rep:open ; rep:chan "e" ; rep:file ( [rep:var "path" ] "/" [rep:var "DocName"] "/" [rep:var "name"] ".html" ) ] [ rep:do irep:GenIssueDetail ] [ rep:cmd rep:close ; rep:chan "e" ] ) ; rep:else ( [ rep:cmd rep:write ; rep:chan "t" ; rep:data irep:NoDetail ] ) ] ) ] ) ; rep:else ( [ rep:cmd rep:write ; rep:chan "t" ; rep:data irep:TableEmpty ] ) ] [ rep:cmd rep:write ; rep:chan "t" ; rep:data irep:DocFoot ] ) ] ) . # Write issue details to channel "e" irep:GenIssueDetail a rep:Report ; :- ( [ rep:cmd rep:write ; rep:chan "e" ; rep:data irep:IssueDetail1 ] [ rep:cmd rep:for ; rep:pattern irep:IssueSectionPattern ; rep:do ( [ rep:cmd rep:write ; rep:chan "e" ; rep:data irep:IssueDetailSect ] ) ; rep:sep ( [ rep:cmd rep:write ; rep:chan "e" ; rep:data irep:IssueDetailSectSep ] ) ] [ rep:cmd rep:write ; rep:chan "e" ; rep:data irep:IssueDetail2 ] [ rep:cmd rep:for ; rep:pattern irep:IssueHistoryPattern ; rep:do ( [ rep:cmd rep:write ; rep:chan "e" ; rep:data irep:IssueHistory1 ] [ rep:cmd rep:for ; rep:pattern irep:IssueHistoryCitePattern ; rep:do ( [ rep:cmd rep:write ; rep:chan "e" ; rep:data irep:IssueHistoryCite ] ) ] [ rep:cmd rep:write ; rep:chan "e" ; rep:data irep:IssueHistory2 ] ) ] [ rep:cmd rep:write ; rep:chan "e" ; rep:data irep:IssueDetail3 ] ) . #### query patterns #### # About the current document irep:ThisPattern :- ( [ rep:var "thisinfo" ] [ rep:and ( [ rep:uri rdfs:label ] [ rep:var "ThisLabel" ] ), ( [ rep:uri dc:author ] [ rep:var "ThisAuthor" ] ), ( [ rep:uri rdfs:comment ] [ rep:var "ThisComment" ] ) ] ) . # Target document info pattern irep:DocPattern :- ( [ rep:var "docinfo" ] [ rep:and ( [ rep:uri rdf:type ] [ rep:uri iss:Document ] ), ( [ rep:uri iss:name ] [ rep:var "DocName" ] ), ( [ rep:uri iss:cite ] [ rep:var "DocURI" ] ), ( [ rep:uri rdfs:label ] [ rep:var "DocLabel" ] ), ( [ rep:uri rdfs:comment ] [ rep:var "DocComment" ] ) ] ) . # Target document editor pattern irep:DocEditorPattern :- ( [ rep:var "docinfo" ] [ rep:uri iss:editor ] [ rep:var "DocEditor" ] [ rep:and ( [ rep:uri foaf:name ] [ rep:var "DocEditorName" ] ), ( [ rep:uri foaf:mbox ] [ rep:var "DocEditorMbox" ] ) ] ) . # Target document history pattern irep:DocHistoryPattern :- ( [ rep:var "docinfo" ] [ rep:uri iss:history ] [ rep:var "DocHistory" ] rep:element [ rep:var "DocHistoryItem" ] [ rep:and ( [ rep:uri iss:status ] [ rep:var "DocHistoryStatus" ] ), ( [ rep:uri iss:when ] [ rep:var "DocHistoryWhen" ] ), ( [ rep:uri iss:cite ] [ rep:var "DocHistoryCite" ] ), ( [ rep:opt ( [ rep:uri rdfs:comment ] [ rep:var "DocHistoryComment" ] ) ] ) ] ) . # General issue info irep:IssuePattern :- ( [ rep:var "issue" ] [ rep:and ( [ rep:uri iss:name ] [ rep:var "name" ] ), ( [ rep:uri rdfs:label ] [ rep:var "label" ] ), ( [ rep:uri iss:raisedBy ] [ rep:var "raisedBy" ] [ rep:and ( [ rep:uri foaf:mbox ] [ rep:var "RaisedByMbox" ] ), ( [ rep:uri foaf:name ] [ rep:var "RaisedByName" ] ), ( [ rep:uri foaf:initials ] [ rep:var "RaisedByInit" ] ) ] ), ( [ rep:uri iss:raisedCite ] [ rep:var "RaisedCite" ] ) , ( [ rep:opt ( [ rep:uri iss:owner ] [ rep:var "owner" ] [ rep:uri foaf:initials ] [ rep:var "OwnerInit" ] ) ] ), ( [ rep:uri iss:status ] [ rep:var "status" ] ) , ( [ rep:uri iss:when ] [ rep:var "when" ] ) ] ) . # Detailed issue info irep:IssueDetailPattern :- ( [ rep:var "issue" ] [ rep:and ( [ rep:uri rdfs:comment ] [ rep:var "comment" ] ), ( [ rep:uri iss:raisedDate ] [ rep:var "RaisedDate" ] ) , ( [ rep:opt ( [ rep:uri iss:owner ] [ rep:var "owner" ] [ rep:and ( [ rep:uri foaf:mbox ] [ rep:var "OwnerMbox" ] ), ( [ rep:uri foaf:name ] [ rep:var "OwnerName" ] ) ] ) ] ), ( [ rep:opt ( [ rep:uri iss:resolvedDate ] [ rep:var "ResolvedDate" ] [ rep:uri iss:resolvedCite ] [ rep:var "ResolvedCite" ] ) ] ) ] ) . # Issue section number references may be repeated.. irep:IssueSectionPattern :- ( [ rep:var "issue" ] [ rep:uri iss:sectionRef ] [ rep:var "SectionRef" ] ) . # History entry is a list.. irep:IssueHistoryPattern :- ( [ rep:var "issue" ] [ rep:uri iss:history ] [ rep:var "IssueHistory" ] rep:element [ rep:var "IssueHistoryItem" ] [ rep:and ( [rep:uri iss:status] [rep:var "IssueHistoryStatus"] ), ( [rep:uri iss:when] [rep:var "IssueHistoryWhen"] ), ( [rep:opt ( [rep:uri rdfs:comment] [rep:var "IssueHistoryComment"] )] ) ] ) . irep:IssueHistoryCitePattern :- ( [ rep:var "IssueHistoryItem" ] [rep:uri iss:cite] [rep:var "IssueHistoryCite"] ) . #### output templates #### irep:ThisHead :- ( "" rep:nl "" rep:nl "" [rep:var "ThisLabel"] "" rep:nl "" rep:nl "" rep:nl rep:nl "

" [rep:var "ThisLabel"] "

" rep:nl "

Prepared by: " [rep:var "ThisAuthor"] "

" rep:nl "

" [rep:var "ThisComment"] "

" rep:nl ) . irep:DocHead1 :- ( "

Document information

" rep:nl "
" rep:nl "
Document identifier:
" [ rep:var "DocName" ] "
" rep:nl "
Document title:
" [ rep:var "DocLabel" ] "
" rep:nl "
Document URI:
" [ rep:var "DocURI" ] "
" rep:nl "
Document editor(s):
" rep:nl ) . irep:DocEditor :- ( "
" [ rep:var "DocEditorName" ] "
" rep:nl ) . irep:DocHead2 :- ( "
" rep:nl "

" [ rep:var "DocComment" ] "

" rep:nl rep:nl "

Document history

" rep:nl "
" rep:nl ) . irep:DocHistory :- ( "
" [rep:var "DocHistoryWhen"] ": " [rep:local "DocHistoryStatus"] "
" rep:nl "
" rep:nl "

See: " [rep:var "DocHistoryCite"] "

" rep:nl "

" [rep:var "DocHistoryComment"] "

" rep:nl ) . irep:DocHead3 :- ( "
" rep:nl "

Issue list

" rep:nl "" rep:nl "" rep:nl "" rep:nl "" rep:nl "" rep:nl "" rep:nl "" rep:nl "" rep:nl "" rep:nl ) . irep:TableItem :- ( "" rep:nl "" rep:nl "" rep:nl "" rep:nl "" rep:nl "" rep:nl "" rep:nl "" rep:nl ) . irep:NoDetail :- ( "" rep:nl ) . irep:TableEmpty :- ( "" rep:nl ) . irep:DocFoot :- ( "

Issue name

By

Description

Owner

Status

Date

" [rep:var "name"] "" [rep:var "RaisedByInit"] "" [rep:var "label"] "" [ rep:if [rep:defined "OwnerInit"] ; rep:do ( [ rep:var "OwnerInit" ] ) ] "" [ rep:local "status" ] "" [ rep:var "when" ] "
No detail found for issue" [rep:var "name"] "
No issues found
" rep:nl rep:nl ) . irep:ThisFoot :- ( "" rep:nl "" rep:nl ) . irep:IssueDetail1 :- ( "

Issue name: " [rep:var "name"] "

" rep:nl "

" [rep:var "label"] "

" rep:nl "
" rep:nl "
Raised by:
" "
" [rep:var "RaisedByName"] "
" rep:nl "
Raised on:
" [rep:var "RaisedDate"] "
" rep:nl "
Raised in message:
" "
" [rep:var "RaisedCite"] "
" rep:nl "
Target document section reference(s):
" rep:nl ) . irep:IssueDetailSect :- ( "" [rep:var "SectionRef"] "" ) . irep:IssueDetailSectSep :- ( "
" rep:nl ) . irep:IssueDetail2 :- ( "
" rep:nl "
Status:
" [rep:local "status"] "
" rep:nl "
Last updated:
" [rep:var "when"] "
" rep:nl "
Owner:
" "
" [rep:var "OwnerName"] "
" rep:nl [ rep:if [rep:defined "ResolvedDate"] ; rep:do ( "
Resolved:
" "
" [rep:var "ResolvedDate"] "
" rep:nl ) ] "
" rep:nl "

Details

" rep:nl "
" [rep:var "comment"] "
" rep:nl "

History

" rep:nl "
" rep:nl) . irep:IssueHistory1 :- ( "
" [rep:var "IssueHistoryWhen"] ": " [rep:local "IssueHistoryStatus"] "
" rep:nl "
" rep:nl ) . irep:IssueHistoryCite :- ( "

See: " [rep:var "IssueHistoryCite"] "

" rep:nl ) . irep:IssueHistory2 :- ( "

" [rep:var "IssueHistoryComment"] "

" rep:nl ) . irep:IssueDetail3 :- ( "
" rep:nl ) . irep:NoReport :- ( "

Nothing found to report.

" rep:nl ) . ''' Usage = ''' python N3GenDocIssues.py options Options are: -i file,file,... input files -o dir output directory -t name generate HTML table to named file -e generate HTML entries to subdirectories ''' #--------------------------------------------------------------------------- # Setup methods #--------------------------------------------------------------------------- def __init__( self, argv ): """ Initialize and process command line options Parameters: argv list of command line arguments: -i file,file,... input files -o dir output directory -t name generate HTML table to named file -e generate HTML entries to subdirectories """ RegStr = StringIO.StringIO( N3GenDocIssues.RegDef ) self.Model = N3Model( RegStr ) #### # self.Model.setPrefixTable( None ) # self.Model.read( RegStr ) #### self.Files = [] self.Output = "" self.Table = None self.Entries = None i = 1 while i < len(argv): if argv[i] == "-i": i += 1 if i >= len(argv): raise N3CommandError( "Input file(s) expected" ) for f in string.split(argv[i],","): if not os.access( f, os.R_OK ): raise N3CommandError( "Cannot read file "+f ) self.Files.append( f ) elif argv[i] == "-o": i += 1 if i >= len(argv): raise N3CommandError( "Output directory expected" ) o = argv[i] if not os.access( o, os.W_OK ): raise N3CommandError( "Cannot write directory "+o ) self.Output = o elif argv[i] == "-t": i += 1 if i >= len(argv): raise N3CommandError( "HTML output filename expected" ) t = argv[i] self.Table = t elif argv[i] == "-e": self.Entries = 1 i += 1 # End while if not self.Model.parseOK(): raise N3QueryError( "Registry generator query error" ) return def readData( self ): """ Read data from files specified on command line. """ for f in self.Files: sys.stdout.write( "Reading file "+f+"...\n" ) s = open( f, "r" ) m = N3Model( s ) s.close() if not m.parseOK(): raise N3ReadError( "Invalid data file", f ) self.Model.merge( m ) return def makeReport( self, ReportNodeName ): """ Generate report files from model data. """ hrep_Report = self.Model.makeNode( ReportNodeName ) Report = N3Report( self.Model, hrep_Report ) self.debug( "Output: "+`self.Output` ) VarBindings = { "file": N3Node( lit="TestReport.html" ), "path": N3Node( lit=self.Output ) } if self.Table: VarBindings["htmlname"] = N3Node( lit=self.Table ) if self.Entries: VarBindings["entries"] = N3Node( lit="1" ) Report.generate( VarBindings ) return def debug( self, msg ): sys.stdout.write( "N3GenDocIssues: "+msg+"\n" ) return # End of N3GenDocIssues #--------+---------+---------+---------+---------+---------+---------+---------+ # Stand-alone test/command line operation code follows: # if __name__ == '__main__': # Process command line arguments sys.stdout.write( "Initializing\n" ) try: argv = sys.argv sys.stdout.write( "argv "+`argv`+", len="+`len(argv)`+"\n" ) if not argv or len(argv) <= 1: argv = [ "N3GenDocIssues", "-i", "N3GenDocIssuesTest.n3", "-o", ".", "-t", "N3GenDocIssuesTest.html" , "-e" ] GenDocIssues = N3GenDocIssues( argv ) except N3CommandError, e: sys.stdout.write( str(e)+"\n" ) sys.stdout.write( N3GenDocIssues.Usage ) sys.exit( 1 ) except N3QueryError, e: sys.stdout.write( str(e)+"\n" ) sys.exit( 9 ) # Read model data sys.stdout.write( "Read data files\n" ) try: GenDocIssues.readData() except N3ReadError, e: sys.stdout.write( "Error reading file "+e.File+"\n" ) sys.stdout.write( str(e)+"\n" ) sys.exit( 2 ) except N3PrefixError, e: sys.stdout.write( str(e)+"\n" ) sys.exit( 2 ) # Generate registry data sys.stdout.write( "Generate document issues report\n" ) try: GenDocIssues.makeReport( "irep:GenReport" ) except N3GenerateError, e: sys.stdout.write( str(e)+"\n" ) sys.exit( 3 ) except N3ReportError, e: sys.stdout.write( str(e)+"\n" ) sys.exit( 3 ) sys.stdout.write( "Exiting\n" ) sys.exit( 0 ) #--------+---------+---------+---------+---------+---------+---------+---------+ # $Log: N3GenDocIssues.py,v $ # Revision 1.6 2002/11/26 17:42:03 graham # Add submitter initials to issue summary table # # Revision 1.5 2002/09/26 13:48:08 graham # Add owner initials to issue table # # Revision 1.4 2002/09/26 13:41:22 graham # Add owner initials to issue table # # Revision 1.3 2002/09/19 15:07:25 graham # Updated document issue report generator to support document details, # document history, issue histories, and tidy up output. # # Revision 1.2 2002/09/10 17:11:35 graham # Initial running version # # Revision 1.1 2002/09/10 16:25:29 graham # Initial version of document issues report generator #