##############################################################################
#
# Copyright (c) 2002 Zope Foundation and Contributors.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
""" Customizable ZSQL methods that come from the filesystem. """
 
import logging
 
from AccessControl.SecurityInfo import ClassSecurityInfo
from Acquisition import ImplicitAcquisitionWrapper
from App.class_init import InitializeClass
from App.special_dtml import DTMLFile
import Globals # for data
from Products.ZSQLMethods.SQL import SQL
 
from Products.CMFCore.DirectoryView import registerFileExtension
from Products.CMFCore.DirectoryView import registerMetaType
from Products.CMFCore.FSObject import FSObject
from Products.CMFCore.permissions import View
from Products.CMFCore.permissions import ViewManagementScreens
from Products.CMFCore.utils import _dtmldir
 
logger = logging.getLogger('CMFCore.FSZSQLMethod')
 
 
class FSZSQLMethod(SQL, FSObject):
 
    """FSZSQLMethods act like Z SQL Methods but are not directly
    modifiable from the management interface."""
 
    meta_type = 'Filesystem Z SQL Method'
 
    manage_options = ({'label':'Customize', 'action':'manage_customise'},
                      {'label':'Test', 'action':'manage_testForm',
                       'help':('ZSQLMethods','Z-SQL-Method_Test.stx')},
                     )
 
    security = ClassSecurityInfo()
    security.declareObjectProtected(View)
 
    # Make mutators private
    security.declarePrivate('manage_main')
    security.declarePrivate('manage_edit')
    security.declarePrivate('manage_advanced')
    security.declarePrivate('manage_advancedForm')
    manage=None
 
    security.declareProtected(ViewManagementScreens, 'manage_customise')
    manage_customise = DTMLFile('custzsql', _dtmldir)
 
    def __init__(self, id, filepath, fullname=None, properties=None):
        FSObject.__init__(self, id, filepath, fullname, properties)
 
    def _createZODBClone(self):
        """Create a ZODB (editable) equivalent of this object."""
        # I guess it's bad to 'reach inside' ourselves like this,
        # but Z SQL Methods don't have accessor methdods ;-)
        s = SQL(self.id,
                self.title,
                self.connection_id,
                self.arguments_src,
                self.src)
        s.manage_advanced(self.max_rows_,
                          self.max_cache_,
                          self.cache_time_,
                          self.class_name_,
                          self.class_file_,
                          connection_hook=self.connection_hook,
                          direct=self.allow_simple_one_argument_traversal)
        return s
 
    def _readFile(self, reparse):
        """Read the data from the filesystem.
        """
        file = open(self._filepath, 'r') # not 'rb', as this is a text file!
        try:
            data = file.read()
        finally:
            file.close()
 
        # parse parameters
        parameters={}
        start = data.find('<dtml-comment>')
        end   = data.find('</dtml-comment>')
        if start==-1 or end==-1 or start>end:
            raise ValueError,'Could not find parameter block'
        block = data[start+14:end]
 
        for line in block.split('\n'):
            pair = line.split(':',1)
            if len(pair)!=2:
                continue
            parameters[pair[0].strip().lower()]=pair[1].strip()
 
        # check for required parameters
        try:
            connection_id =   ( parameters.get('connection id', '') or
                                parameters['connection_id'] )
        except KeyError,e:
            raise ValueError("The '%s' parameter is required "
                             "but was not supplied" % e)
 
        # Optional parameters
        title =           parameters.get('title','')
        arguments =       parameters.get('arguments','')
        max_rows =        parameters.get('max_rows',1000)
        max_cache =       parameters.get('max_cache',100)
        cache_time =      parameters.get('cache_time',0)
        class_name =      parameters.get('class_name','')
        class_file =      parameters.get('class_file','')
        connection_hook = parameters.get('connection_hook',None)
        direct = parameters.get('allow_simple_one_argument_traversal', None)
 
        self.manage_edit(title, connection_id, arguments, template=data)
 
        self.manage_advanced(max_rows,
                             max_cache,
                             cache_time,
                             class_name,
                             class_file,
                             connection_hook=connection_hook,
                             direct=direct)
 
        # do we need to do anything on reparse?
 
 
    if Globals.DevelopmentMode:
        # Provide an opportunity to update the properties.
        def __of__(self, parent):
            try:
                self = ImplicitAcquisitionWrapper(self, parent)
                self._updateFromFS()
                return self
            except:
                logger.exception("Error during __of__")
                raise
 
InitializeClass(FSZSQLMethod)
 
registerFileExtension('zsql', FSZSQLMethod)
registerMetaType('Z SQL Method', FSZSQLMethod)