def recycle(self, rbID, trans):
        """
        Moves the item to the specified recycle bin.
        
        The item then becomes inaccesible.
        
        @param rbID: The id of the destination container, which must be
                     a L{RecycleBin} instance
        @type rbID: str
        
        @param trans: A valid transaction handle 
        
        @return: None
        """
        trans.actions.append( (self.recycle, (rbID, trans)) )
        try:
            oUser = currentThread().session.user
            self = db.getItem(self._id, trans)
        
            iUserRole = objectAccess.getAccess(self, oUser)
            bCanDelete = (iUserRole > objectAccess.AUTHOR) or \
                (iUserRole == objectAccess.AUTHOR and self._owner == oUser._id)
        
            if (not(self._isSystem) and bCanDelete):
                oDeleted = DeletedItem(self)
    
                oDeleted._owner = oUser._id
                oDeleted._created = time.time()
                oDeleted.modifiedBy = oUser.displayName.value
                oDeleted.modified = time.time()
                oDeleted._parentid = rbID
                db.handle_update(oDeleted, None, trans)
                db.putItem(oDeleted, trans)
    
                # delete item logically
                self._recycle(trans)
                
                # save container
                oParent = db.getItem(self._parentid, trans)
                oParent._removeItemReference(self)
                db.putItem(oParent, trans)
                
                #update recycle bin
                oRecycleBin = db.getItem(rbID, trans)
                if not(oDeleted.getContentclass() in oRecycleBin.containment):
                    raise serverExceptions.ContainmentError
                oRecycleBin._addItemReference(oDeleted)
                db.putItem(oRecycleBin, trans)
            else:
                raise serverExceptions.PermissionDenied

        except serverExceptions.DBTransactionIncomplete:
            trans.retry()
    def appendTo(self, parent, trans):
        """
        Adds the item to the specified container.

        @param parent: The id of the destination container or the container
            itself
        @type parent: str OR L{Container}
        
        @param trans: A valid transaction handle
        
        @return: None
        """
        trans.actions.append( (self.appendTo, (parent, trans)) )
        try:
            if type(parent)==str:
                oParent = db.getItem(parent, trans)
            else:
                oParent = parent
            oUser = currentThread().session.user
    
            iUserRole = objectAccess.getAccess(oParent, oUser)
            if iUserRole == objectAccess.READER:
                raise serverExceptions.PermissionDenied
            if not(self.getContentclass() in oParent.containment):
                raise serverExceptions.ContainmentError
    
            # set security to new item
            if iUserRole == objectAccess.COORDINATOR:
                # user is COORDINATOR
                self._applySecurity(oParent, trans)
            else:
                # user is not COORDINATOR
                self.inheritRoles = True
                self.security = oParent.security
#            if trans._retries == 0:
#                raise serverExceptions.DBTransactionIncomplete    
            self._owner = oUser._id
            self._created = time.time()
            self.modifiedBy = oUser.displayName.value
            self.modified = time.time()
            self._parentid = oParent._id
            db.handle_update(self, None, trans)
            db.putItem(self, trans)
            # update container
            oParent._addItemReference(self)
            db.putItem(oParent, trans)
            
        except serverExceptions.DBTransactionIncomplete:
            trans.retry()
    def _undelete(self, deletedItem, trans):
        """
        Undeletes a logically deleted item.
        
        Returns: None
        """
        db.handle_update(deletedItem, None, trans)
        deletedItem._isDeleted = False
        
        if deletedItem.isCollection:
            lstChildren = deletedItem._items.values() + deletedItem._subfolders.values()
            for sID in lstChildren:
                oChild = db.getDeletedItem(sID, trans)
                self._undelete(oChild, trans)

        db.putItem(deletedItem, trans)
 def update(self, trans):
     """
     Updates the item.
     
     @param trans: A valid transaction handle
         
     @return: None
     """
     trans.actions.append( (self.update, (trans, )) )
     try:
         oOldItem = db.getItem(self._id, trans)
         
         oUser = currentThread().session.user
         iUserRole = objectAccess.getAccess(oOldItem, oUser)
         
         if iUserRole > objectAccess.READER:
             # set security
             if iUserRole == objectAccess.COORDINATOR:
                 # user is COORDINATOR
                 if (self.inheritRoles != oOldItem.inheritRoles) or \
                 (not self.inheritRoles and self.security != oOldItem.security):
                     oParent = db.getItem(self._parentid, trans)
                     self._applySecurity(oParent, trans)
             else:
                 # restore previous ACL
                 self.security = oOldItem.security
                 self.inheritRoles = oOldItem.inheritRoles
 
             db.handle_update(self, oOldItem, trans)
             self.modifiedBy = oUser.displayName.value
             self.modified = time.time()
             db.putItem(self, trans)
             
             if self.displayName.value != oOldItem.displayName.value:
                 oParent = db.getItem(self._parentid, trans)
                 oParent._removeItemReference(oOldItem)
                 oParent._addItemReference(self)
                 db.putItem(oParent, trans)
         else:
             raise serverExceptions.PermissionDenied
     
     except serverExceptions.DBTransactionIncomplete:
         trans.retry()
    def on_update(item, new_attr, old_attr, trans):
        # check containment
        if [obj for obj in new_attr.value
            if obj.getContentclass() != new_attr.compositeClass]:
            raise serverExceptions.ContainmentError
        
        dctObjects = {}
        for obj in new_attr.value:
            obj._containerid = item._id
            dctObjects[obj._id] = obj
            
        new_ids = sets.Set([obj._id for obj in new_attr.value])
        
        # get previous value
        if old_attr:
            old_ids = sets.Set(old_attr.value)
        else:
            old_ids = sets.Set()

        # calculate added composites
        lstAdded = list(new_ids - old_ids)
        for sID in lstAdded:
            db.handle_update(dctObjects[sID], None, trans)
            dctObjects[sID]._isDeleted = False
            db.putItem(dctObjects[sID], trans)
            
        # calculate constant composites
        lstConstant = list(new_ids & old_ids)
        for sID in lstConstant:
            db.handle_update(dctObjects[sID], db.getItem(sID, trans) , trans)
            db.putItem(dctObjects[sID], trans)

        # calculate removed composites
        lstRemoved = list(old_ids - new_ids)
        for sID in lstRemoved:
            composite4removal = db.getItem(sID, trans)
            CompositionEventHandler.removeComposite(composite4removal, trans)
            
        new_attr.value = list(new_ids)
    def _copy(self, target, trans, clearRolesInherited=False):
        oCopy = self.clone()
        if clearRolesInherited:
            oCopy.inheritRoles = False

        oUser = currentThread().session.user
        oCopy._owner = oUser._id
        oCopy._created = time.time()
        oCopy.modifiedBy = oUser.displayName.value
        oCopy.modified = time.time()
        oCopy._parentid = target._id
        
        db.handle_update(oCopy, None, trans)
        db.putItem(oCopy, trans)

        if self.isCollection:
            lstChildrentIds = self._items.values() + self._subfolders.values()
            for sId in lstChildrentIds:
                child = db.getItem(sId, trans)
                if child and objectAccess.getAccess(child, oUser):
                    child._copy(oCopy, trans)

        target._addItemReference(oCopy)
        db.putItem(target, trans)