########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Server/Server/SCore/XmlDocumentImp.py,v 1.23 2005/02/25 10:20:03 mbrown Exp $
"""
XmlDocument 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 cStringIO, types

import RawFileImp

from Ft.Server import FTSERVER_NAMESPACE
from Ft.Server.Common import ResourceTypes, Schema, ValidationInfo, XmlLib
from Ft.Server.Server import FtServerServerException, Error
from Ft.Server.Server.Drivers import FtssDriver
from Ft.Server.Server.Lib import SwishHelper
from Ft.Xml.Domlette import Print


class XmlDocumentImp(RawFileImp.RawFileImp):
    """
    A specialized raw file resource, that is an XML document
    """
    resourceType = ResourceTypes.ResourceType.XML_DOCUMENT

    def getDocumentDefinition(self):
        """
        Get the document definition associated with this document
        """
        self._verifyTx()
        stmts = self._driver.getSystemModel().complete(
            self._path.absolutePath, Schema.DOCDEF, None
            )
        if not len(stmts):
            return None
        docDef = stmts[0].object
        if docDef == Schema.NULL_DOCDEF:
            return None
        docDef = self._basePath.normalize(docDef)
        return self._fetchResource(docDef)

    def getValidationInfo(self):
        """
        Get the validation information associated with this resource.
        """
        self._verifyTx()
        docDef = self.getDocumentDefinition()
        if docDef:
            return docDef.getCreationParams().validationInfo
        return ValidationInfo.NoValidation()

    def setContent(self, src):
        """
        Set the string content of this resource
        """
        self._verifyTx()
        if not isinstance(src, types.StringType):
            if type(src) != type(u''):
                raise TypeError("src must be a string object, instead its a: %s"%(type(src)))
            else:
                src=src.encode('utf-8')

        self._driver.updateResourceContent(self._path, src)

        if self.getDocumentDefinition() and self.getDocumentDefinition().getCreationParams().fullTextIndex:
            SwishHelper.Index(self._path.absolutePath,
                              self.getContent(),
                              self.getRoot())

        #See if it needs to be validated
        self._validateNewSrc(src)
        return

    def expandXLink(self):
        """
        Return the content of this resource with all XLinks expanded

        NOT IMPLEMENTED.
        """
        raise NotImplementedError("XLink expansion not implemented")


    def setDocumentDefinition(self, newDocDef):
        """
        Reset our document definition and regenerate our self
        """
        if newDocDef is None:
            ddPath = Schema.NULL_DOCDEF
        else:
            ddPath = newDocDef.getAbsolutePath()

        #Sadly XUpdate does not support attribute mutation so we will have to do it the long way
        md = self.getMetaDataResource()
        dom = md.asDom()
        dom.documentElement.setAttributeNS(None, 'document-definition', ddPath)
        st = cStringIO.StringIO()
        Print(dom, stream=st)
        self._driver.updateResourceMetadata(self._path, st.getvalue(),changeDocDef = 1)
        return

    def _delete(self):
        """
        Check if we are being indexed, if so reindex (#FIXME: performance hit)
        """
        docDef = self.getDocumentDefinition()
        if docDef and docDef.getCreationParams().fullTextIndex:
            self.reindex()
        return RawFileImp.RawFileImp._delete(self)

    def _validateNewSrc(self,src):
        """Validate a new source document"""
        dd = self.getDocumentDefinition()
        if dd is not None:
            cp = dd.getCreationParams()
            if cp.validationInfo is not None:
                if not cp.validationInfo.validate(self.getRoot(), src, self._path.absolutePath):
                    raise FtServerServerException(Error.VALIDATION_ERROR,
                                                  message='Document Failed Validation')


def NewXmlDocumentXml(driver, path, acl, owner, imt, src, docDef, typ):
    a = driver.aclToXml(acl)
    t = FtssDriver.CurrentTime()
    md = """<ftss:MetaData xmlns:ftss="%s" path='%s' type='%s' creation-date='%s' document-definition='%s'>
  %s
  <ftss:LastModifiedDate>%s</ftss:LastModifiedDate>
  <ftss:Owner>%s</ftss:Owner>
  <ftss:Imt>%s</ftss:Imt>
  <ftss:Size>%d</ftss:Size>
</ftss:MetaData>
        """ % (FTSERVER_NAMESPACE,
               path,
               Schema.g_rdfResourceTypes[typ],
               t,
               docDef or Schema.NULL_DOCDEF,
               a,
               t,
               owner,
               imt,
               len(src))
    return XmlLib.MakeString(md)
