# -*- coding: utf8 -*-
'''
**********************************************
*       P R O T O C O L - B A S E - C L A S S
*       for any protocol
**********************************************
$RCSfile: base_protocol.py,v $
$Revision: 926 $
$Author: markus $
$Date: 2008-05-07 14:26:47 +0200 (Mi, 07. Mai 2008) $

'''

import types
from biocase.wrapper.errorclasses         import *
from biocase.wrapper.psf import ProviderSetup

import biocase.configuration
cfg = biocase.configuration.Cfg()

import logging
log = logging.getLogger("pywrapper.protocol")
# this logger is used to log requests!
logRequestOnly = logging.getLogger("pywrapper.protocol.request")


# ------------------------------------------------------------------------------------
class ProtocolBaseClass:
    '''The main protocol class accepting a standard API and managing requests and responses.'''
    NAME="abstract protocol"
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def __init__(self, dsaObj, diagnosticsHandler, RequestClass, ResponseClass):
        self.dsaObj       = dsaObj
        self.requestObj   = RequestClass(dsaObj)
        self.responseObj  = ResponseClass(dsaObj, diagnosticsHandler)
        # please set this when database was used
        self.dbmodVersion = None
    
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def parseRequest(self, args):
        '''Get request args from parameter or CGI and create & process a request object.
        Pass the specific request class to be used with the method.'''
        self.requestObj.parseRequest(args)
        
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def doResponse(self, stream, encoding, httpHeader):
        '''Process request and print out the response into the given stream.'''
        try:
            log.debug("DO_RESPONSE: process request")
            self.processRequest()
        except PyWrapperError:
            log.info("Request processing failed")
        except:
            log.error("UNKNOWN ERROR DURING REQUEST PROCESSING")
        try:
            log.debug("DO_RESPONSE: postprocess")
            self.responseObj.postprocessMessage(self.requestObj, self.dbmodVersion)
        except PyWrapperError:
            log.info("Message postprocessing failed")
        except:
            log.error("UNKNOWN ERROR DURING MESSAGE POSTPROCSSING")
        try:
            log.debug("DO_RESPONSE: printResponse")
            self.responseObj.printResponse(stream, encoding, httpHeader)
        except PyWrapperError:
            log.info("Sending message response failed")
        except:
            log.error("UNKNOWN ERROR WHILE RESPONDING THE MESSAGE")
        try:
            log.debug("DO_RESPONSE: logging request")
            self.logRequest()
        except PyWrapperError:
            log.info("Request logging failed")
        except:
            log.error("UNKNOWN ERROR DURING REQUEST LOGGING")
            

    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def processRequest(self):
        '''Override this to implement the operational logic to process a request.'''
        raise "PLEASE IMPLEMENT IN SUBCLASS"

    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def logRequest(self):
        '''Basic request logging for all protocolls. Implement logProtocolSpecific() if other protocols want to log more information'''
        try:
            specific=self.logProtocolSpecific()
        except:
            specific = "LogError"
        logRequestOnly.info("%s [%s] %s %s" %(self.psfObj.sourcename.upper(), self.__class__.NAME, self.requestObj.remoteHost, specific))

    def logProtocolSpecific(self):
        '''Override this if other protocols want to log more information about a request and its response'''
        return ""
        
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def getPsfObj(self):
        return self.dsaObj.getPSFObj()
    psfObj = property(getPsfObj)
    