# -*- coding: utf8 -*-
'''
**********************************************
*       P R O T O C O L - C L A S S
*       for the biocase protocol
**********************************************
$RCSfile: biocase_protocol.py,v $
$Revision: 911 $
$Author: markus $
$Date: 2008-04-30 23:52:39 +0200 (Mi, 30. Apr 2008) $

Request and Response classes to support the biocase protocol.
'''

import types
from biocase.wrapper.errorclasses         import *
from biocase.wrapper.dbmod.base_dbmod    import DBBasemodule
from biocase.wrapper.protocol.base_protocol import ProtocolBaseClass
from biocase.wrapper.protocol.BioCASe.biocase_request  import RequestClass
from biocase.wrapper.protocol.BioCASe.biocase_response import ResponseClass
from biocase.wrapper.psf import ProviderSetup

import logging
log = logging.getLogger("pywrapper.protocol.biocase")


# ------------------------------------------------------------------------------------
class ProtocolClass(ProtocolBaseClass):
    '''The main protocol class accepting a standard API and managing requests and responses.'''
    NAME="BioCASe"
    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def __init__(self, dsaObj, diagnosticsHandler):
        log.info("BioCASe protocol used.")
        ProtocolBaseClass.__init__(self, dsaObj, diagnosticsHandler, RequestClass=RequestClass, ResponseClass=ResponseClass)

    def logProtocolSpecific(self):
        '''Return BioCASe specific logging info for both request and response'''
        logDetails = "[%s]"%self.requestObj.type
        if self.requestObj.count > 0:
            logDetails = "[count]"
        if self.requestObj.type in ["scan","search"]:
            logDetails += " %i/%i" % (self.requestObj.start, self.requestObj.limit)
            try:
                logDetails += " q=%s"%unicode(self.requestObj.filter)
            except:
                log.exception("Cant log request filter!")
            if self.requestObj.type == "scan" and self.requestObj.scan is not None:
                    logDetails += " scan=%s"%self.requestObj.scan
        logDetails += " %s"%str(self.responseObj.recordStatus)
        return logDetails

    # _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
    def processRequest(self):
        '''Starts to process the request and prepares output object.'''
        # capabilities
        if self.requestObj.type == "capabilities":
            log.debug("process capabilities request")
            self.responseObj.setCapabilitiesContent()
        # purely static CMFs
        elif self.requestObj.type == "static":
            log.debug("process static request")
            # create CMF object of the response-CMF for output of XML
            try:
                # build new CMF object
                CMFObject = CMFClass()
                CMFObject.loadCMFdata(self.psfObj.getCMFfilename(self.requestObj.resSchema), psfObj=self.psfObj)
            except CouldNotPickleError:
                pass
            except:
                raise CMFError(cmf=self.requestObj.resSchema)
            etree = CMFObject.createXMLResultET( [[]] )
            self.responseObj.setSearchContent(etree, self.resultStatus)
        # search or scan
        elif self.requestObj.type in ("search", "scan"):
            # chose DBmodule, connect to DB.
            from biocase.wrapper.operations import getOperationsObjectForDBMod
            operationObj = getOperationsObjectForDBMod(self.psfObj, self.responseObj)
            # remember dbmod in response object for protocol header generation later on
            self.dbmodVersion = DBBasemodule.__repr__(operationObj)        
            # search or scan
            if self.requestObj.type == "scan":
                #scan
                log.debug("process scan request")
                scanList = operationObj.scan(self.requestObj)
                # copy list to response object
                self.responseObj.setScanContent(scanList)
            else:
                # SEARCH
                log.debug("process search request")
                # check if requested schemas are supported for output
                self.requestObj.areSchemasSupported()
                # check whether full result or hit-count is requested
                if self.requestObj.count:
                    # count hits (integer)
                    log.debug("do count")
                    x = operationObj.count(self.requestObj)
                    # copy count to the response object
                    self.responseObj.setCountContent(x)
                else:
                    log.debug("do full search")
                    (self.resultET, self.resultStatus) = operationObj.search(self.requestObj)
                    log.debug("successful end of search request incl ET creation")
                    # copy result to the response object
                    if self.resultET is None:
                        log.warn("No result returned from search operation")
                    else:
                        self.responseObj.setSearchContent(self.resultET, self.resultStatus)
        else:
            log.warn("Unknown Request-type : " + str(self.requestObj.type))
