########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Server/Server/SCore/GroupImp.py,v 1.17 2005/01/07 19:48:38 jkloth Exp $
"""
Group repository resource class

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

import XmlDocumentImp, GroupableObjectMixin

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 FtssDriver
from Ft.Xml import XPath
from Ft.Xml.XLink import XLINK_NAMESPACE

class GroupImp(XmlDocumentImp.XmlDocumentImp,
               GroupableObjectMixin.GroupableObjectMixin):
    """
    Contains implementation for a group resource which is a set of specified users
    """
    resourceType = ResourceTypes.ResourceType.GROUP

    def addMember(self, user):
        """
        Add a member to this group
        """
        if not (user.isResourceType(ResourceTypes.ResourceType.USER) or user.isResourceType(ResourceTypes.ResourceType.GROUP)):
            raise FtServerServerException(Error.INVALID_GROUP_MEMBER,
                                          type=user.getResourceType())

        if user.getMetaDataResource().getAbsolutePath() in self.getMemberPaths():
            uName = user.getName()
            raise FtServerServerException(Error.ALREADY_GROUP_MEMBER,
                                          groupName=self._path.absolutePath,
                                          userName=user.getAbsolutePath())

        xu = NEW_GROUP_MEMBER_XUPDATE%(FTSERVER_NAMESPACE,XLINK_NAMESPACE,
                                       user.getPath().absolutePath)
        xu = XmlLib.MakeString(xu)
        self._driver.xupdateContent(self._path, xu)

    def getMembers(self):
        """
        Get a list of all the users that are members of this group
        """
        res = []
        for path in self.getMemberPaths():
            path = self._basePath.normalize(path)
            res.append(self._fetchResource(path))
        return res

    def getMemberPaths(self):
        """
        Get a list of names of all users that are members of this group
        """
        return map(lambda x: x.object[:-9],
                   self._driver.getSystemModel().complete(self.getAbsolutePath(),
                                                          Schema.GROUP_MEMBER,
                                                          None))

    def removeMember(self, user):
        """
        Remove a user from this group
        """
        if user.getAbsolutePath() not in self.getMemberPaths():
            uName = user.getName()
            raise FtServerServerException(Error.ALREADY_GROUP_MEMBER,
                                          groupName=self._path,
                                          userName=uName)

        xu = REMOVE_GROUP_MEMBER_XUPDATE%(FTSERVER_NAMESPACE,XLINK_NAMESPACE,
                                          user.getAbsolutePath())
        xu = XmlLib.MakeString(xu)
        self._driver.xupdateContent(self._path, xu)

    _usernameExpression = XPath.Compile('string(ftss:Group/@name)')
    def getUsername(self):
        """
        Get the username of this group
        """
        self._verifyTx()
        con = self.toXPathContext()
        res = self._usernameExpression.evaluate(con)
        return res

def NewGroupXml(driver, name, path, acl, owner, docDef):
    content = """<ftss:Group xmlns:ftss="%s" name='%s'>
  <ftss:Members/>
</ftss:Group>""" % (FTSERVER_NAMESPACE,name)
    content = XmlLib.MakeString(content)
    
    a = driver.aclToXml(acl)
    t = FtssDriver.CurrentTime()
    docDef = docDef or Schema.NULL_DOCDEF
    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>text/xml</ftss:Imt>
  <ftss:Size>%d</ftss:Size>
</ftss:MetaData>
        """ % (FTSERVER_NAMESPACE, path,
               Schema.g_rdfResourceTypes[ResourceTypes.ResourceType.GROUP],
               t, docDef, a, t, owner, len(content))
    return XmlLib.MakeString(md), content


NEW_GROUP_MEMBER_XUPDATE="""<xupdate:modifications
  version="1.0"
  xmlns:xupdate="http://www.xmldb.org/xupdate"
  xmlns:ftss="%s"
  xmlns:xlink="%s"
>
  <xupdate:append select="/ftss:Group/ftss:Members" child="last()">
    <ftss:MemberReference xlink:type="simple" xlink:href="%s;metadata" xlink:actuate="onLoad" xlink:show="embed"/>
  </xupdate:append>
</xupdate:modifications>
"""


REMOVE_GROUP_MEMBER_XUPDATE="""<xupdate:modifications
  version="1.0"
  xmlns:xupdate="http://www.xmldb.org/xupdate"
  xmlns:ftss="%s"
  xmlns:xlink="%s"
>
  <xupdate:remove select="/ftss:Group/ftss:Members/ftss:MemberReference[@xlink:href='%s;metadata']"/>
</xupdate:modifications>
"""


