########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Server/Server/SCore/XsltDocumentImp.py,v 1.23 2005/03/22 17:36:58 mbrown Exp $
"""
XsltDocument repository resource class.

Copyright 2005 Fourthought, Inc. (USA).
Detailed license and copyright information: http://4suite.org/COPYRIGHT
Project home, documentation, distributions: http://4suite.org/
"""

import XmlDocumentImp

from Ft.Lib import Uri
from Ft.Server import FTSERVER_NAMESPACE
from Ft.Server.Common import ResourceTypes, Schema, XmlLib
from Ft.Server.Server import FtServerServerException, Error
from Ft.Server.Server.Drivers import FtssInputSource
from Ft.Xml import Xslt
from Ft.Xml.Xslt import StylesheetReader


class XsltDocumentImp(XmlDocumentImp.XmlDocumentImp):
    """
    An Xslt Document
    """
    resourceType = ResourceTypes.ResourceType.XSLT_DOCUMENT

    def asStylesheet(self):
        """
        Returns this resource as an Xslt stylesheet
        """
        self._verifyTx()
        #See if anything was changed
        st = None
        if self._hasModifiedDependencies(self._path.absolutePath):
            #Force a recompile
            try:
                self.setContent(self.getContent())
            except FtServerServerException, e:
                if e.errorCode == Error.PERMISSION_DENIED:
                    print "A file that %s depends on has changed.  The repository normally tries to       recompile and update it in this case, but the current user does not have        permission to do so.  This is usually not a serious problem, except that        it slows down the loading of this XSLT."%self.getAbsolutePath()

                    isrc = FtssInputSource.FtssInputSourceFactory.fromString(
                            self.getContent(),
                            self._path.absolutePathAsUri,
                            self._driver)

                    reader = StylesheetReader.StylesheetReader()
                    # register extension elements with the reader
                    # NOTE: this is only needed for compiled stylesheets as
                    #  the Processor interface will take care of this
                    functions, elements = self.getExtFunctionsAndElements()
                    reader.addExtensionElementMapping(elements)

                    st = reader.fromSrc(isrc)
                    pass
                else:
                    raise
        if not st:
            r = StylesheetReader.StylesheetReader()
            st = r.fromInstant(self._driver.fetchResourceCache(self._path),
                               self._path.absolutePathAsUri)
        return st

    def setContent(self, src):
        XmlDocumentImp.XmlDocumentImp.setContent(self, src)

        isrc = FtssInputSource.FtssInputSourceFactory.fromString(src,
                   self._path.absolutePathAsUri,
                   self._driver)

        reader = StylesheetReader.StylesheetReader()
        # register extension elements with the reader
        # NOTE: this is only needed for compiled stylesheets as
        #  the Processor interface will take care of this
        functions, elements = self.getExtFunctionsAndElements()
        reader.addExtensionElementMapping(elements)

        sty = reader.fromSrc(isrc)

        #Compile the stylesheet
        self._driver.setResourceCache(self._path, sty.root)

    def setDocumentDefinition(self, newDocDef):
        """
        Reset our document definition and regenerate our self
        """
        XmlDocumentImp.XmlDocumentImp.setDocumentDefinition(self, newDocDef)
        #In case there was a doc def change
        self.setContent(self.getContent())

    def getExtFunctionsAndElements(self):
        """
        """
        #All resource get to use the builtin functions
        functions, elements = XmlDocumentImp.XmlDocumentImp.getExtFunctionsAndElements(self)
        specified_funcs, specified_elems = self._recursiveGetExtFunctionsAndElements(functions, elements)
        functions.update(specified_funcs)
        elements.update(specified_elems)
        return functions, elements

    def _recursiveGetExtFunctionsAndElements(self, functions, elements):
        dd = self.getDocumentDefinition()
        if dd:
            cp = dd.getCreationParams()
            if cp:
                f, e = cp.getExtFunctionsAndElements()
                #The dictionaries passed in override the "newer" ones
                f.update(functions)
                e.update(elements)
                functions, elements = (f, e)
        model = self._driver.getSystemModel()
        for stmt in model.complete(self.getAbsolutePath(), Schema.STYLESHEET_DEPENDENCY, None):
            res = self.fetchResource(stmt.object)
            f, e = res._recursiveGetExtFunctionsAndElements(functions, elements)
            f.update(functions)
            e.update(elements)
            functions, elements = (f, e)
        return functions, elements

    def _hasModifiedDependencies(self, path):
        model = self._driver.getSystemModel()
        curLmd = model.complete(path, Schema.MODIFIED_DATE, None)[0].object

        for stmt in model.complete(path, Schema.STYLESHEET_DEPENDENCY,None):
            testPath = Uri.BaseJoin(path, stmt.object)
            test = model.complete(testPath, Schema.MODIFIED_DATE,None)
            if test and test[0].object > curLmd:
                return 1
            if self._hasModifiedDependencies(testPath): return 1
        return 0

