########################################################################
# $Header: /var/local/cvsroot/4Suite/Ft/Server/Client/Core/ContainerClient.py,v 1.24 2005/04/07 00:16:46 jkloth Exp $
"""
4Suite: an open-source platform for XML and RDF processing.

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

from __future__ import generators
import warnings

from Ft.Server.Common import ResourceTypes
from Ft.Server.FtRpc import Commands

import XmlDocumentClient


class ContainerClient(XmlDocumentClient.XmlDocumentClient):
    """
    A repository container
    """
    ###################################
    #Creation Interfaces
    ###################################
    def createDocument(self, path, src, docDef=None, imt='text/xml',
                       forcedType=None):
        """
        Creates a document with the given document definition name,
        path, type, and source.  if the type is not specified it will
        attempt to infer the type based on IMT and the src.
        If path is an empty string, then a UUID will be generated for
        the XML, XSLT, and Schematron documents.
        If the document definition specifies a full text index, then
        the content is indexed
        """
        path = Commands.RemoteMethodCommand(
                   'createDocument', self._path,
                   (path, src, docDef, imt, forcedType)
               ).send(self._connection).results
        #try:
        #except FtServerClientException:
        #    raise Exception("Resource %s added twice in the same setup specification"%path)
        return self.fetchResource(path)

    def createContainer(self, path, createParents=0, docDef=None,
                        actualContent=None):
        """
        Creates the specified container, if createParents is true
        then all its parents along the path are created (if they
        dont exist).
        """
        path = Commands.RemoteMethodCommand(
            'createContainer', self._path,
            (path, createParents, docDef, actualContent)
            ).send(self._connection).results

        return self.fetchResource(path)


    def createGroup(self, name, docDef=None):
        """
        Creates a new group.  You need write access to the system group container
        """
        path = Commands.RemoteMethodCommand(
            'createGroup', self._path,
            (name, docDef)).send(self._connection).results

        return self.fetchResource(path)


    def createUser(self, name, passHash, docDef=None):
        """
        Create a new user.  You must have write access to te system group container
        """
        path = Commands.RemoteMethodCommand(
            'createUser', self._path,
            (name, passHash, docDef)).send(self._connection).results

        return self.fetchResource(path)


    def createXPathDocumentDefinition(self, path, nss, maps, cp, docDef=None):
        path = Commands.RemoteMethodCommand(
            'createXPathDocumentDefinition', self._path,
            (path, nss, maps, cp, docDef)
            ).send(self._connection).results

        return self.fetchResource(path)


    def createXsltDocumentDefinition(self, path, xsltSrc, cp, docDef=None):
        """Create an XSLT document definition from pieces"""
        path = Commands.RemoteMethodCommand(
            'createXsltDocumentDefinition', self._path,
            (path, xsltSrc, cp, docDef)
            ).send(self._connection).results

        return self.fetchResource(path)


    def createRawFile(self, path, imt, src):
        """
        Creates a raw file resource, using the specified, path, internet media type, and source string.
        """
        path = Commands.RemoteMethodCommand('createRawFile',
                                            self._path,
                                            (path, imt, src)
                                            ).send(self._connection).results

        return self.fetchResource(path)

    def createUriReferenceFile(self, path, imt, srcUri):
        """
        Create an URI Reference file.  An URI Reference file is a reference to a URI
        """
        path = Commands.RemoteMethodCommand(
            'createUriReferenceFile', self._path,
            (path, imt, srcUri)
            ).send(self._connection).results

        return self.fetchResource(path)



    ######################################
    #Delete Interface
    ######################################
    def deleteResource(self, path, traverseAliases=None):
        """
        Delete any resource from the system.
        """
        if (traverseAliases != None):
            warnings.warn("You are using a deprecated traverse alias feature.  Please specify with path arguments ;traverse or ;no-traverse",
                  DeprecationWarning, 2)
        if traverseAliases:
            path += ";traverse"
        else:
            path += ";no-traverse"
        res = self.fetchResource(path)
        res.delete()
        return

    ########################################
    #Temporary file Interfaces
    ########################################
    def setPathTemporary(self, path, timeToLive):
        """
        Marks the specified repository object as temporary
        """
        res = self.fetchResource(path)
        res.markTemporary(timeToLive)
        return

    #########################################
    #Access interfaces
    #########################################
    #User List and Dict interfaces
    def __len__(self):
        """Overides the length operator"""
        return Commands.RemoteMethodCommand('__len__',
                                            self._path,
                                            ()
                                            ).send(self._connection).results


    def __getitem__(self, i):
        """Implements list access for containers and repositories"""

        #Because of how python does list iteration, we need to verify that the index
        #is within our ranges here, or that we have the specified key
        if isinstance(i, (int, long)):
            # sequence interface
            ourLen = len(self)
            if not -ourLen <= i < ourLen:
                raise IndexError(i)
        else:
            # mapping interface
            if not self.has_key(i):
                raise KeyError(i)

        path = Commands.RemoteMethodCommand('__getitem__',
                                            self._path,
                                            (i,)
                                            ).send(self._connection).results
        return self.fetchResource(path+';no-traverse')

    def __getslice__(self, i, j):
        """Implements list slice access for containers and repositories"""
        paths = Commands.RemoteMethodCommand('__getslice__',
                                            self._path,
                                            (i,j)
                                            ).send(self._connection).results
        res = []
        for p in paths:
            res.append(self.fetchResource(p))
        return res


    def index(self, item):
        """User List interface"""
        return self[:].index(item)

    def keys(self):
        """User Dict interface"""
        return Commands.RemoteMethodCommand('keys',
                                            self._path,
                                            ()
                                            ).send(self._connection).results

    def iterkeys(self):
        """User Dict interface"""
        return iter(self.keys())

    def values(self):
        """User Dict interface"""
        return self[:]

    def itervalues(self):
        """User Dict interface"""
        for key in self.iterkeys():
            yield self[key]

    def items(self):
        """User Dict interface"""
        return map(None, self.keys(), self.values())

    def iteritems(self):
        """User Dict interface"""
        for key in self.iterkeys():
            yield key, self[key]

    def has_key(self, key):
        """User Dict interface"""
        return key in self.keys()

    __contains__ = has_key

    def get(self, key, failobj=None):
        """User Dict interface"""
        if self.has_key(key):
            return self[key]
        return failobj
