@python -x %~f0 %* & goto :EOF


import DCOracle
import os
import re
import string
import sys
import time
import win32api
import win32con

from com.creo.araxi.database import GetAccountInfo
from pywintypes import FALSE, TRUE

EXIT_SUCCESS = 0
EXIT_FAILURE = 1
RESERVED = 0

TIME_FORMAT = '%Y-%b-%d %H:%M:%S'
DB_TIME_FORMAT = 'YYYY-Mon-DD HH24:MI:SS'

monthNum = {1:'Jan', 2:'Feb', 3:'Mar', 4:'Apr', 5:'May', 6:'Jun', 7:'Jul', 8:'Aug', 9:'Sep', 10:'Oct', 11:'Nov', 12:'Dec' }

#Date Formats
reTIME_DDMONYY   = '^(\d{1,2})\W([A-Za-z]{3})\W(\d{1,2})'         #DD-Mon-YY
reTIME_DDMONYYYY = '^(\d{1,2})\W([A-Za-z]{3})\W(\d{4})'           #DD-Mon-YYYY
reTIME_DDMMYYYY  = '^(\d{1,2})\W(\d{1,2})\W(\d{4})'               #DD-MM-YYYY
reTIME_DDMMYY    = '^(\d{1,2})\W(\d{1,2})\W(\d{1,2})'             #DD-MM-YY
reTIME_MONDDYYYY = '^([A-Za-z]{3})\W(\d{1,2})\W(\d{4})'           #Mon-DD-YYYY
reTIME_MONDDYY   = '^([A-Za-z]{3})\W(\d{1,2})\W(\d{1,2})'         #Mon-DD-YY
reTIME_YYYYMONDD = '^(\d{4})\W([A-Za-z]{3})\W(\d{1,2})'           #YYYY-Mon-DD
reTIME_YYYYMMDD  = '^(\d{4})\W(\d{1,2})\D(\d{1,2})'               #YYYY-MM-DD


#Time HH:MM:SS
reTIME = '([0-2][0-9]:[0-5][0-9]:[0-5][0-9])'

ARAXIHOME = os.environ['AraxiHome']
HLOG_PROPERTIES_PATH = os.path.join( ARAXIHOME, 'CreoAraxi\etc\hlog.properties' )

# Dictionary pointers
# DBCS_HistLogAction table 
aHISTLOGACTIONID                = 0
aHISTLOGACTIONNUM               = 1
aHISTLOGACTIONCATEGORYNUM       = 2
aUSERNAME                       = 3
aHISTLOGACTIONCREATEDTM         = 4
aHISTLOGPARAMCOUNT              = 5
aHISTLOGCHRONOSEQNUM            = 6
aHISTLOGACTIONDETLCNT           = 7
aHISTLOGACTIONMAXDETLSEVERITYCD = 8
aHISTLOGACTIONMAXDETLCHRONONUM  = 9
aHISTLOGPARAM1                  = 10
aHISTLOGPARAM2                  = 11
aHISTLOGPARAM3                  = 12
aHISTLOGPARAM4                  = 13
aHISTLOGPARAM5                  = 14
aHISTLOGPARAM6                  = 15
aHISTLOGPARAM7                  = 16
aHISTLOGPARAM8                  = 17
aHISTLOGPARAM9                  = 18
aHISTLOGPARAM10                 = 19

# DBCS_HistLogDetail table
dHISTLOGDETAILID                = 0
dHISTLOGACTIONID                = 1
dHISTLOGDETAILNUM               = 2
dHISTLOGDETAILSEVERITYCD        = 3
dHISTLOGDETAILCREATEDTM         = 4
dHISTLOGPARAMCOUNT              = 5
dHISTLOGCHRONOSEQNUM            = 6
dJCKDID                         = 7
dHISTLOGPARAM1                  = 8 
dHISTLOGPARAM2                  = 9
dHISTLOGPARAM3                  = 10
dHISTLOGPARAM4                  = 11 
dHISTLOGPARAM5                  = 12
dHISTLOGPARAM6                  = 13
dHISTLOGPARAM7                  = 14
dHISTLOGPARAM8                  = 15
dHISTLOGPARAM9                  = 16
dHISTLOGPARAM10                 = 17

# self.dictJobs  = {}
JOBNAME   = 0
JOBSERVER = 1
JOBSHARE  = 2
JOBPATH   = 3

# self.dictHistoryByChronoSeq = {}
HBCS_NAME = 0
HBCS_TYPE = 1
HBCS_ID   = 2
HBCS_DATE = 3
HBCS_INFO = 4
HBCS_CAT  = 5

SYSTEMGUID = r'AnGXeGB\7TAnGXeGB\7T'

ACTION = 'A'
DETAIL = 'D'
CATEGORY = 'C'
DEFAULT_ACTION_JOBNAME = '*NO_JOB_NAME*'
DEFAULT_DETAIL_JOBNAME = '**NO_JOB_NAME**'
DEFAULT_DELIMITER = '\t'
DEFAULT_DISPLAY_FORMAT = '%s%s%-19s%s%-20s%s%-10s%s%-10s%s%s'
CUSTOM_DISPLAY_FORMAT= '%s%s%s%s%s%s%s%s%s%s%s'


# Help screen
USAGE_TEXT = \
'''\

Display Prinergy history in chronological order.

Usage: HistLog -from <date><time> -to <date><time> [-job <jobname>] [-action] [-detail] [-delim <delimiter>] [-h]

Options:
    -from                       \tStarting date/time in the format <date> <time>
    -to                         \tEnding date/time in the format <date> <time>
                                \tThe date format can be one of:
                                \t    DD Mon YYYY
                                \t    DD Mon YY
                                \t    DD MM YYYY
                                \t    DD MM YY
                                \t    Mon DD YYYY
                                \t    Mon DD YY
                                \t    YYYY Mon DD
                                \t    YYYY MM DD
                                \tAny non-alphanumeric character can be used as
                                \ta separator between the day, month and year.
                                \tThe time is in 24 hour format:
                                \t    HH:MM:SS
    -job                        \tDisplay history for a job
    -action                     \tDisplay history actions only
    -detail                     \tDisplay history details only
    -delim                      \tDelimiter to separate fields during output. (defaults to tab)
    -?, -h, -help               \tshow help

                                \tDefault starting time is current date/time - 1 hour.
                                \tDefault ending time is current date/time

'''

def main():

    _fromDate, _toDate, actions, details, job, verbose, delimiter = GetOpts()
    machineName = win32api.GetComputerName()

    node = PrinergyNodeInfo( None )
    node.Query()
    primaryServer = node.GetPrimaryNodeName()
    prinergyVersion = node.GetCurrentRelease()

    print 'Prinergy primary server is: %s '  % primaryServer
#    print 'Prinergy version is %s' % prinergyVersion

    if _fromDate == None:
        fromDate = time.strftime( TIME_FORMAT, time.localtime( time.time() - 3600 ) )
    else:
        fromDate = _fromDate

    if _toDate == None:
        toDate = time.strftime( TIME_FORMAT, time.localtime( time.time() ) )
    else:
        toDate = _toDate

    fromDate = ConvertDateTime( fromDate )
    toDate   = ConvertDateTime( toDate )

    print 'Getting history from %s up to %s.' % ( fromDate, toDate )

    try:
        hLog = HistLog()
        hLog.GetHistory( fromDate, toDate, actions, details, job )
        hLog.PrintHistory( delimiter)

    except:
        errorType, errorValue = sys.exc_info()[:2]
        print 'ERROR: %s %s'  % ( str(errorType), str(errorValue) )

class HistLog:
    def __init__( self ):
        self.myDb = Db( )

    def GetHistory( self, fromDate, toDate, actions = TRUE, details = TRUE, job = None ):
        self.fromDate = fromDate
        self.toDate = toDate
        self.actions = actions
        self.details = details
        self.job = job
        self.GetJacketData()
        self.GetActions()
        self.GetDetails()

    def GetJacketData( self ):
        jobQuery = \
            '''\
            SELECT JckdId
                 , JckdName
                 , JckdRootFolderServerName
                 , JckdRootFolderShareName
                 , JckdRootFolderPathName
            FROM DBCS_Jacket
            '''
        jobInfo = self.myDb.Query( jobQuery )
  
        # Create a dictionary of jobs.
        # Key is job id, and value consists of a tuple in the format:
        #     JobName (offset 0), Servername (offset 1), sharename (offset 2), pathname (offset 3)

        self.dictJobIds = {}

        self.dictJobs  = {}
        JOBNAME   = 0
        JOBSERVER = 1
        JOBSHARE  = 2
        JOBPATH   = 3

        for (jckdId, jckdName, jckdRootFolderServerName, jckdRootFolderShareName, jckdRootFolderPathName) in jobInfo:
            # Add job into dictionary. 
            self.dictJobs[ jckdId ] = ( jckdName, jckdRootFolderServerName, jckdRootFolderShareName, jckdRootFolderPathName)
            # create dictionary which maps job names to jckdIds
            self.dictJobIds[ string.upper( jckdName ) ] = jckdId

        # add system guid to dictionary
        self.dictJobs[ SYSTEMGUID ] = ( '* SYSTEM *', '', '', '')

        self.jobList = []
        for entry in self.dictJobs.values():
            self.jobList.append( entry[ 0 ] )
  
    def GetActions( self ):
        self.dictHistoryByChronoSeq = {}
        HBCS_NAME = 0
        HBCS_TYPE = 1
        HBCS_ID   = 2
        HBCS_DATE = 3
        HBCS_INFO = 4
        HBCS_CAT  = 5

        self.dictHistLogCategories = GenerateHistLogPropertiesDictionary( CATEGORY )
#        print self.dictHistLogCategories

        # Get history actions

        self.dictHistLogActions = GenerateHistLogPropertiesDictionary( ACTION )

        actionsQuery = \
            '''\
            SELECT HISTLOGACTIONID
                 , HISTLOGACTIONNUM
                 , HISTLOGACTIONCATEGORYNUM
                 , USERNAME
                 , HISTLOGACTIONCREATEDTM
                 , HISTLOGPARAMCOUNT
                 , HISTLOGCHRONOSEQNUM
                 , HISTLOGACTIONDETLCNT
                 , HISTLOGACTIONMAXDETLSEVERITYCD
                 , HISTLOGACTIONMAXDETLCHRONONUM
                 , HISTLOGPARAM1
                 , HISTLOGPARAM2
                 , HISTLOGPARAM3
                 , HISTLOGPARAM4
                 , HISTLOGPARAM5
                 , HISTLOGPARAM6
                 , HISTLOGPARAM7
                 , HISTLOGPARAM8
                 , HISTLOGPARAM9
                 , HISTLOGPARAM10
            FROM DBCS_HistLogAction 
            WHERE HISTLOGACTIONCREATEDTM >= to_date( \'%s\' , \'%s\' )
            AND   HISTLOGACTIONCREATEDTM <= to_date( \'%s\' , \'%s\' )
            ''' % ( self.fromDate, DB_TIME_FORMAT, self.toDate, DB_TIME_FORMAT )
    
    #    print actionsQuery

        hLogActions = self.myDb.Query( actionsQuery )
    
        #
        # build 2 dictionaries.
        # one dictionary contains all history (both actions and details)
        #     key    = HistLogChronoSeqNum
        #     values = tuple consisting of job or user name, history type, id, date, history object
        # the other contains only actions
        #     key    = HistLogActionId
        #     values = filler - "* NO JOB NAME *" will be replaced with the job name when we 
        #              query the DBCS_HistLogDetail table.
        #
    
        self.dictJobsByActionId = {}
    
        type = ACTION
        for item in hLogActions:
            actionId           = item[ aHISTLOGACTIONID ]
            actionNum          = item[ aHISTLOGACTIONNUM ]
            actionCategoryNum  = item[ aHISTLOGACTIONCATEGORYNUM ]
            actionUserName     = item[ aUSERNAME ]
            actionDate         = item[ aHISTLOGACTIONCREATEDTM ]
            actionChronoSeqNum = item[ aHISTLOGCHRONOSEQNUM ]
            actionParamCount   = item[ aHISTLOGPARAMCOUNT ]
    
            actionParams = []
            for count in range( 0, actionParamCount ):
                actionParams.append( item[ aHISTLOGPARAM1 + count] )
    
            self.dictJobsByActionId[ actionId ] = DEFAULT_ACTION_JOBNAME
   
            actionParams = tuple( actionParams )
            actionString = self.dictHistLogActions[ str( actionNum ) ]
            strAction    = SubstituteParams( actionString, actionParams, actionParamCount )
            self.dictHistoryByChronoSeq[ actionChronoSeqNum ] = ( actionUserName, type, actionId, actionDate, strAction, self.dictHistLogCategories[ str( actionCategoryNum ) ] )


    def GetDetails( self ):    
        # Get history details
        self.dictHistLogDetails = GenerateHistLogPropertiesDictionary( DETAIL )
    
        detailsQuery = \
            '''\
            SELECT HISTLOGDETAILID
                 , HISTLOGACTIONID
                 , HISTLOGDETAILNUM
                 , HISTLOGDETAILSEVERITYCD
                 , HISTLOGDETAILCREATEDTM
                 , HISTLOGPARAMCOUNT
                 , HISTLOGCHRONOSEQNUM
                 , JCKDID
                 , HISTLOGPARAM1
                 , HISTLOGPARAM2
                 , HISTLOGPARAM3
                 , HISTLOGPARAM4
                 , HISTLOGPARAM5
                 , HISTLOGPARAM6
                 , HISTLOGPARAM7
                 , HISTLOGPARAM8
                 , HISTLOGPARAM9
                 , HISTLOGPARAM10
            FROM DBCS_HistLogDetail 
            WHERE HISTLOGDETAILCREATEDTM >= to_date( \'%s\' , \'%s\' )
            AND   HISTLOGDETAILCREATEDTM <= to_date( \'%s\' , \'%s\' )
            ''' % ( self.fromDate, DB_TIME_FORMAT, self.toDate, DB_TIME_FORMAT )
    #    print detailsQuery

        if self.job != None:
            jobList = ''
            if re.search( '\*', self.job ):
                for key in self.dictJobs.keys():
#                    print self.dictJobs[ key ] [ JOBNAME ], self.job
                    jobnameFilter = string.upper( string.replace( self.job, '*', '.*' ) )
                    if re.search( '^%s$' %jobnameFilter, self.dictJobs[ key ] [ JOBNAME ]):
                        jobList = jobList + '\'%s\', ' % key

                if jobList != '':
                    jobList = re.sub(  ', $', '', jobList )
                    detailsQuery = detailsQuery + 'AND JCKDID IN ( %s )' % jobList
                else:
                    raise Exception( 'The specified job is not in the database.' )

            else:

                if self.job in self.jobList:
                    detailsQuery = detailsQuery + 'AND JCKDID = \'%s\'' % self.dictJobIds[ string.upper( self.job ) ]

                else:
                    raise Exception( 'The specified job is not in the database.' )
  
        hLogDetails = self.myDb.Query( detailsQuery )
    
        type = DETAIL
        for item in hLogDetails:
            jobId              = item[ dJCKDID ]
            detailId           = item[ dHISTLOGDETAILID ]
            detailNum          = item[ dHISTLOGDETAILNUM ]
            detailActionId     = item[ dHISTLOGACTIONID ]
            detailChronoSeqNum = item[ dHISTLOGCHRONOSEQNUM ]
            detailDate         = item[ dHISTLOGDETAILCREATEDTM ]
            detailParamCount   = item[ dHISTLOGPARAMCOUNT ]
  
            detailParams = []
            for count in range(0, detailParamCount):
                detailParams.append( item[ dHISTLOGPARAM1 + count] )
            if self.dictJobs.has_key( jobId ):
                jobName      = self.dictJobs[ jobId ] [ JOBNAME ]
            else:
                jobName = DEFAULT_DETAIL_JOBNAME
            if self.actions == TRUE:
                self.dictJobsByActionId[ detailActionId ] = jobName
            detailParams = tuple( detailParams )
            detailString = self.dictHistLogDetails[ str(detailNum) ]
            strDetail    = SubstituteParams( detailString, detailParams, detailParamCount )
            self.dictHistoryByChronoSeq[ detailChronoSeqNum ] = ( jobName, type, detailId, detailDate, strDetail, detailActionId )
   
    def PrintHistory( self, delimiter = ' ' ):
        if len( self.dictHistoryByChronoSeq ) == 0:
            print 'No history for time period between %s and %s' % ( self.fromDate, self.toDate )
        else:
            if delimiter == None:
                delimiter = DEFAULT_DELIMITER
                displayFormat = DEFAULT_DISPLAY_FORMAT
            else:
                displayFormat = CUSTOM_DISPLAY_FORMAT

            print displayFormat % ( 'Job name', delimiter, 'Date Time', delimiter, 'Id', delimiter, 'User', delimiter, 'Category', delimiter, 'Information' )
            print displayFormat % ( '--------', delimiter, '---------', delimiter, '--', delimiter, '----', delimiter, '--------', delimiter, '-----------' )
            keys = self.dictHistoryByChronoSeq.keys()
            keys.sort()
            for chronoSeqNum in keys:
                msg = ''

                if self.dictHistoryByChronoSeq[ chronoSeqNum ] [ HBCS_TYPE ] == ACTION:
                    if self.job != None and self.dictJobsByActionId[  self.dictHistoryByChronoSeq[ chronoSeqNum ] [ HBCS_ID ] ] == DEFAULT_ACTION_JOBNAME:
                        pass # don't print history action with the job name of *NO_JOB_NAME* if a job was specified
                             # these are actions which are not associated with a job (destroyed jobs?)
                    else:

                        # print history actions
#                        msg = msg + '%s' % self.dictJobsByActionId[  self.dictHistoryByChronoSeq[ chronoSeqNum ] [ HBCS_ID ] ] # job name
#                        msg = msg + delimiter + '%s' % self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_DATE]   # time of day
#                        msg = msg + delimiter + '%s' % self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_ID]     # action id
#                        msg = msg + delimiter + '%s' % self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_NAME]   # user name
#                        msg = msg + delimiter + '%s' % self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_CAT ]   # action category
#                        msg = msg + delimiter + '%s' % self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_INFO]   # action info

                        msg =\
                            displayFormat %\
                            (\
                                self.dictJobsByActionId[  self.dictHistoryByChronoSeq[ chronoSeqNum ] [ HBCS_ID ] ], delimiter,\
                                self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_DATE], delimiter,\
                                self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_ID],   delimiter,\
                                self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_NAME], delimiter,\
                                self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_CAT ], delimiter,\
                                self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_INFO]\
                            )

                else:
                    # print history details
#                    msg = msg + '%s' % self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_NAME]               # job name
#                    msg = msg + delimiter + '%s' % self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_DATE]   # time of day
#                    msg = msg + delimiter + '%s' % self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_CAT]    # action id
#                    msg = msg + delimiter                                                                   # blank
#                    msg = msg + delimiter                                                                   # blank
#                    msg = msg + delimiter + '%s' % self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_INFO]   # detail info
                    msg =\
                        displayFormat %\
                        (\
                            self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_NAME], delimiter,\
                            self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_DATE], delimiter,\
                            self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_CAT],  delimiter,\
                            '', delimiter,\
                            '', delimiter,\
                            self.dictHistoryByChronoSeq[ chronoSeqNum ][HBCS_INFO]\
                        )

                if msg != '':
                    print msg
    
def GetOpts():

    fromDate = None	
    toDate   = None
    actions  = TRUE
    details  = TRUE
    job      = None
    verbose  = FALSE
    delimiter = None

    argc = len( sys.argv )
    i = 1
    while i < argc:
        arg = sys.argv[i]
        argUC = string.upper( arg )
        if argUC in [ '-?', '-H', '-HELP' ]:
            PrintUsageAndExit()
        elif argUC == '-FROM':
            i = i + 1
            if ( i >= argc ):
                PrintUsageAndExit( 'Option %s requires an additional argument' % arg, EXIT_FAILURE )
            fromDate =  sys.argv[i] 
        elif argUC == '-TO':
            i = i + 1
            if ( i >= argc ):
                PrintUsageAndExit( 'Option %s requires an additional argument' % arg, EXIT_FAILURE )
            toDate =  sys.argv[i] 
        elif argUC == '-ACTIONS':
            details = FALSE
        elif argUC == '-DETAILS':
            actions =  FALSE
        elif argUC == '-JOB':
            i = i + 1
            if ( i >= argc ):
                PrintUsageAndExit( 'Option %s requires an additional argument' % arg, EXIT_FAILURE )
            job =  sys.argv[i] 
        elif argUC == '-DELIM':
            i = i + 1
            if ( i >= argc ):
                PrintUsageAndExit( 'Option %s requires an additional argument' % arg, EXIT_FAILURE )
            delimiter =  sys.argv[i] 
        elif argUC == '-V':
            verbose = TRUE
        else:
            PrintUsageAndExit()
        i = i + 1
    return fromDate, toDate, actions, details, job, verbose, delimiter


class Db:
    def __init__( self ):
        user, password, alias = GetAccountInfo.OracleAccountInfo()
        oracleLogin = user + '/' + password + '@' + alias
        self.dbConnection = DCOracle.Connect( oracleLogin )
        self.dbCursor = self.dbConnection.cursor()


    def Query( self, query ):
        self.dbCursor.execute( query )
        return self.dbCursor.fetchall()

    def Commit( self ):
        self.dbConnection.commit()

    def Close( self ):
        self.dbConnection.close()


def SubstituteParams( historyString, historyParams, historyParamCount ):
    newString = historyString

    for item in range( 0, historyParamCount ):
#        print str( historyParams[ item ] )
        newString = string.replace( newString, '{%s}' % item , str( historyParams[ item ] ) )
    newString = string.replace(  string.replace( newString, '\n', '' ), 'String=', '' )
    return newString

def GenerateHistLogPropertiesDictionary( type ):

    if os.path.isfile( HLOG_PROPERTIES_PATH ):
        hHLogProperties = open( HLOG_PROPERTIES_PATH, 'r' )
    else:
        print 'Nuts'

    dict = {}
    dictCategories = {}

    if type == ACTION:
        stringRE = '^HistoryLog.Action.*'
    elif type == DETAIL:
        stringRE = '^HistoryLog.Detail.*'
    elif type == CATEGORY:
        stringRE = 'HistoryLog\.Category\.(\d*)\.String=(.*)'

    for line in hHLogProperties.readlines():
        thisLine = re.sub( '#.*', '', line )
           
        if re.search( stringRE, thisLine ):
            splitLine = string.split(  thisLine, '.', 3 )
            histLog   = splitLine[0]
            historyEntry    = splitLine[1]
            historyEntryNum = splitLine[2]
            historyString = splitLine[3]
            if re.search( '^String=', historyString ):
                dict[ historyEntryNum ] = string.replace(  string.replace( historyString, '\n', '' ), 'String=', '' )
    return dict

def ConvertDateTime( dateTime ):

    currentDate = time.strftime( TIME_FORMAT, time.localtime( time.time() ) )
    m = re.search( reTIME_YYYYMONDD, currentDate )
#    print m.groups()
    year = m.group(1)
    century = re.sub( '..$','',year )
    timeOfDay = '00:00:00'
    if re.search( reTIME_DDMONYYYY, dateTime ):
#        print 'Format is %s' % reTIME_DDMONYYYY
        m = re.search( reTIME_DDMONYYYY, dateTime )        
        ( day, month, year ) = m.groups()
    elif re.search( reTIME_YYYYMONDD, dateTime ):
#        print 'Format is %s' % reTIME_YYYYMONDD
        m = re.search( reTIME_YYYYMONDD, dateTime )        
        ( year, month, day ) = m.groups()
    elif re.search( reTIME_DDMONYY, dateTime ):
#        print 'Format is %s' % reTIME_DDMONYY
        m = re.search( reTIME_DDMONYY, dateTime )        
        ( day, month, year ) = m.groups()
        year = '%s%s' % ( century, year )
    elif re.search( reTIME_MONDDYYYY, dateTime ):
#        print 'Format is %s' % reTIME_MONDDYYYY
        m = re.search( reTIME_MONDDYYYY, dateTime )        
        ( month, day, year ) = m.groups()
    elif re.search( reTIME_MONDDYY, dateTime ):
#        print 'Format is %s' % reTIME_MONDDYY
        m = re.search( reTIME_MONDDYY, dateTime )        
        ( month, day, year ) = m.groups()
        year = '%s%s' % ( century, year )
    elif re.search( reTIME_YYYYMMDD, dateTime ):
#        print 'Format is %s' % reTIME_YYYYMMDD
        m = re.search( reTIME_YYYYMMDD, dateTime )        
        ( year, month, day ) = m.groups()
        if monthNum.has_key( int( month ) ):
            month = monthNum[ int( month ) ]
        else:
            print 'Invalid month: %s.' % month
            sys.exit(1)
    elif re.search( reTIME_DDMMYYYY, dateTime ):
#        print 'Format is %s' % reTIME_DDMMYYYY
        m = re.search( reTIME_DDMMYYYY, dateTime )        
        ( day, month, year ) = m.groups()
        if monthNum.has_key( int( month ) ):
            month = monthNum[ int( month ) ]
        else:
            print 'Invalid month: %s.' % month
            sys.exit(1)
    elif re.search( reTIME_DDMMYY, dateTime ):
#        print 'Format is %s' % reTIME_DDMMYY
        m = re.search( reTIME_DDMMYY, dateTime )
        ( day, month, year ) = m.groups()
        if monthNum.has_key( int( month ) ):
            month = monthNum[ int( month ) ]
        else:
            print 'Invalid month: %s.' % month
            sys.exit(1)    
        year = '%s%s' % ( century, year )
    else:
        print 'Date format is unknown.'    
        sys.exit(1)

    m = re.search( reTIME, dateTime )
    if m:
        timeOfDay = m.group(1)

    return '%s-%s-%s %s' % ( year, month, day, timeOfDay )



#
# Get basic information about a Prinergy node.
# Divided into 4 steps:
# 1) Constructor just stores arguments
# 2) Query retrieves information, possibly raising exception
# 3) Format produces text, but does not write to a particular I/O device
# 4) Print writes formatted text to stdout
#
class PrinergyNodeInfo:
    def __init__( self, nodename ):
        self.nodename = NodeName( nodename )
        self.queried = FALSE
        
    def Query( self ):
        hklm = win32api.RegConnectRegistry( self.nodename, win32con.HKEY_LOCAL_MACHINE )
    
        subkey_Araxi = 'Software\\Creo\\Araxi'
        self.CurrentRelease = MyRegQueryValue( hklm, subkey_Araxi, 'CurrentRelease', win32con.REG_SZ )
    
        subkey_Araxi_CurrentRelease = subkey_Araxi + '\\' + self.CurrentRelease
        subkey_Araxi_CurrentRelease_Default = subkey_Araxi_CurrentRelease + '\\' + 'Default'
        subkey_Araxi_CurrentRelease_Default_System = subkey_Araxi_CurrentRelease_Default + '\\' + 'System'
        
        self.PrimaryNodeName = MyRegQueryValue( hklm, subkey_Araxi_CurrentRelease_Default_System, 'PrimaryNodeName', win32con.REG_SZ )
        self.NodeList = MyRegQueryValue( hklm, subkey_Araxi_CurrentRelease_Default_System, 'NodeList', win32con.REG_SZ )
        self.AraxiRootDirectory = MyRegQueryValue( hklm, subkey_Araxi_CurrentRelease_Default_System, 'AraxiRootDirectory', win32con.REG_SZ )
        try:
            # if the machine is a Emergency Plate Making (EPM) machine the OriginalPrimaryNodeName value will exist
            self.OriginalPrimaryNodeName = MyRegQueryValue( hklm, subkey_Araxi_CurrentRelease_Default_System, 'OriginalPrimaryNodeName', win32con.REG_SZ )
        except:
            self.OriginalPrimaryNodeName = None
        
        subkey = 'System\\CurrentControlSet\\Control\\Session Manager\\Environment'
        self.AraxiHomeEnvVar = MyRegQueryValue( hklm, subkey, 'AraxiHome', win32con.REG_SZ )
        
        subkey = 'System\\CurrentControlSet\\Services\\LanmanServer\\Shares'
        AraxiHomeShareInfo = MyRegQueryValue( hklm, subkey, 'AraxiHome', win32con.REG_MULTI_SZ )
        m = re.match( 'Path=(.+)', AraxiHomeShareInfo[1] )
        if m:
            self.AraxiHomeSharePath = m.group( 1 )
        else:
            self.AraxiHomeSharePath = '<Unavailable>'
        
        self.queried = 1
       
    
    def GetPrimaryNodeName( self ):
        if not self.queried:
            return '<Not queried>'

        return self.PrimaryNodeName
        
    def GetNodeName( self ):
        return self.nodename

    def GetCurrentRelease( self ):
        return self.CurrentRelease

#
# produce an NT computer name in 'canonical' form, without leading backslashes
# optional argument may have leading or missing double backslashes
# '.', '' or None is interpreted as the local computer
#
def NodeName( name=None ):
    nodename = ''
    if name:
        nodename = name
    if nodename[:2] == '\\\\':
        nodename = nodename[2:]
        if not nodename:
            nodename = name
            #raise ValueError( 'invalid node name' )
    if nodename == '.':
        nodename = ''
    if not nodename:
        nodename = win32api.GetComputerName()
    return string.upper( nodename )

def MyRegQueryValue( rootkey, subkeypath, valuename, expectedtype=None ):
    '''
    get a registry value and type, optionally checking for expected type,
    and formatting a nice error message if not found or wrong type
    '''
    hkey = None
    try:
        try:
            hkey = win32api.RegOpenKey( rootkey, subkeypath, RESERVED, win32con.KEY_QUERY_VALUE )
        except win32api.error, err:
            if err[0] == winerror.ERROR_FILE_NOT_FOUND:
                raise KeyError( 'registry key not found' )
            else:
                raise err
                
        try:
            v, t = win32api.RegQueryValueEx( hkey, valuename )
            if expectedtype and t != expectedtype:
                raise TypeError( 'wrong registry value type found: %d expected: %d' % ( t, expectedtype ) )
            return v
        except win32api.error, err:
            if err[0] == winerror.ERROR_FILE_NOT_FOUND:
                raise KeyError( 'registry value not found' )
            else:
                raise err
    except win32api.error, err:
        if err[0] == winerror.ERROR_ACCESS_DENIED: # show user friendly message when access is denied
            raise Exception( 'Registry access denied, please log in as an administrator and try again!' )
        else:
            raise


def PrintUsageAndExit( errmsg='', exitcode=EXIT_SUCCESS ):
    if errmsg:
        print errmsg
        print
    print USAGE_TEXT
    sys.exit( exitcode )

if __name__ == '__main__':
    main()