Exemplo n.º 1
0
class PatchedDirectory (FileMeta):

    ftype = fs.DIRECTORY

    EXISTING = 0
    ADDED    = 1
    REMOVED  = 2
    
    def __init__(self, name, parent, uid, gid, mode, mtime_ns):
        FileMeta.__init__(self, name, parent, uid, gid, mode, mtime_ns)
        
        self.adds         = PersistentMapping()
        self.removes      = PersistentMapping()
        self.meta_changes = PersistentMapping() # name => ((to_uid, to_gid, to_mode), (from_uid, from_gid, from_mode))

        self.subdirs      = PersistentMapping()

        self.state        = PatchedDirectory.EXISTING

    def pdbg(self, indent = ''):
        s = { 0 : 'EXISTING', 1 : 'ADDED', 2 : 'REMOVED' }
        
        print indent, 'Dir %s %s' % (s[self.state], self.dbg_meta())
        
        if self.adds:
            print indent, ' ** Adds **'
            for v in self.adds.itervalues():
                v.pdbg( indent + '   ' )
        if self.removes:
            print indent, ' ** Removes **'
            for v in self.removes.itervalues():
                v.pdbg( indent + '   ' )

        if self.meta_changes:
            print indent, ' ** Meta Mods **'
            for k, v in self.removes.iteritems():
                print indent + '   ', k, v

        for s in self.subdirs.itervalues():
            s.pdbg( indent + '   ' )
Exemplo n.º 2
0
class Directory (FileMeta):

    ftype = fs.DIRECTORY
    
    def __init__(self, name, parent, uid, gid, mode, mtime_ns):
        FileMeta.__init__(self, name, parent, uid, gid, mode, mtime_ns)
        
        self.content = PersistentMapping()


    def get_content_set(self):
        return set( (v.name, v.ftype) for v in self.content.itervalues() )

    def get_meta_set(self, filenames):
        s = set()
        for fn in filenames:
            v = self.content[ fn ]
            s.add( (v.name, v.uid, v.gid, v.mode) )
        return s
    def checkBasicOps(self):
        from persistent.mapping import PersistentMapping
        m = PersistentMapping({'x': 1}, a=2, b=3)
        m['name'] = 'bob'
        self.assertEqual(m['name'], "bob")
        self.assertEqual(m.get('name', 42), "bob")
        self.assert_('name' in m)

        try:
            m['fred']
        except KeyError:
            pass
        else:
            self.fail("expected KeyError")
        self.assert_('fred' not in m)
        self.assertEqual(m.get('fred'), None)
        self.assertEqual(m.get('fred', 42), 42)

        keys = m.keys()
        keys.sort()
        self.assertEqual(keys, ['a', 'b', 'name', 'x'])

        values = m.values()
        values.sort()
        self.assertEqual(values, [1, 2, 3, 'bob'])

        items = m.items()
        items.sort()
        self.assertEqual(items,
                         [('a', 2), ('b', 3), ('name', 'bob'), ('x', 1)])

        keys = list(m.iterkeys())
        keys.sort()
        self.assertEqual(keys, ['a', 'b', 'name', 'x'])

        values = list(m.itervalues())
        values.sort()
        self.assertEqual(values, [1, 2, 3, 'bob'])

        items = list(m.iteritems())
        items.sort()
        self.assertEqual(items,
                         [('a', 2), ('b', 3), ('name', 'bob'), ('x', 1)])
Exemplo n.º 4
0
    def checkBasicOps(self):
        from persistent.mapping import PersistentMapping
        m = PersistentMapping({'x': 1}, a=2, b=3)
        m['name'] = 'bob'
        self.assertEqual(m['name'], "bob")
        self.assertEqual(m.get('name', 42), "bob")
        self.assert_('name' in m)

        try:
            m['fred']
        except KeyError:
            pass
        else:
            self.fail("expected KeyError")
        self.assert_('fred' not in m)
        self.assertEqual(m.get('fred'), None)
        self.assertEqual(m.get('fred', 42), 42)

        keys = m.keys()
        keys.sort()
        self.assertEqual(keys, ['a', 'b', 'name', 'x'])

        values = m.values()
        values.sort()
        self.assertEqual(values, [1, 2, 3, 'bob'])

        items = m.items()
        items.sort()
        self.assertEqual(items,
                         [('a', 2), ('b', 3), ('name', 'bob'), ('x', 1)])

        keys = list(m.iterkeys())
        keys.sort()
        self.assertEqual(keys, ['a', 'b', 'name', 'x'])

        values = list(m.itervalues())
        values.sort()
        self.assertEqual(values, [1, 2, 3, 'bob'])

        items = list(m.iteritems())
        items.sort()
        self.assertEqual(items,
                         [('a', 2), ('b', 3), ('name', 'bob'), ('x', 1)])
Exemplo n.º 5
0
    def checkBasicOps(self):
        from persistent.mapping import PersistentMapping

        m = PersistentMapping({"x": 1}, a=2, b=3)
        m["name"] = "bob"
        self.assertEqual(m["name"], "bob")
        self.assertEqual(m.get("name", 42), "bob")
        self.assert_("name" in m)

        try:
            m["fred"]
        except KeyError:
            pass
        else:
            self.fail("expected KeyError")
        self.assert_("fred" not in m)
        self.assertEqual(m.get("fred"), None)
        self.assertEqual(m.get("fred", 42), 42)

        keys = m.keys()
        keys.sort()
        self.assertEqual(keys, ["a", "b", "name", "x"])

        values = m.values()
        values.sort()
        self.assertEqual(values, [1, 2, 3, "bob"])

        items = m.items()
        items.sort()
        self.assertEqual(items, [("a", 2), ("b", 3), ("name", "bob"), ("x", 1)])

        keys = list(m.iterkeys())
        keys.sort()
        self.assertEqual(keys, ["a", "b", "name", "x"])

        values = list(m.itervalues())
        values.sort()
        self.assertEqual(values, [1, 2, 3, "bob"])

        items = list(m.iteritems())
        items.sort()
        self.assertEqual(items, [("a", 2), ("b", 3), ("name", "bob"), ("x", 1)])
Exemplo n.º 6
0
class Book( Persistent ):
    ''' This is a user book to include user's orders, one per user '''
    def __init__(self, user=None):
        self.user = user
        self.orders = PersistentList()
        self.positions = PersistentMapping()

    def addOrder(self, order):
        if order.instrument in self.positions:
            self.positions[order.instrument].append(order)
        else:
            self.positions[order.instrument] = PersistentList(order)

    def cost(self):
        cost=0.0
        for orders in self.positions.itervalues():
            cost += sum([o.cost() for o in orders])
        return

    def marketValue(self):
        mktval = 0.0
        for inst, orders in self.positions.iteritems():
            mktval += inst.marketPrice * sum([o.amountMatched for o in orders])
        return mktval
Exemplo n.º 7
0
class Book( Persistent ):
    ''' This is a user book to include user's orders, one per user '''
    def __init__(self, user=None):
        self.user = user
        self.orders = PersistentList()
        self.positions = PersistentMapping()

    def addOrder(self, order):
        if order.instrument in self.positions:
            self.positions[order.instrument].append(order)
        else:
            self.positions[order.instrument] = PersistentList(order)

    def cost(self):
        cost=0.0
        for orders in self.positions.itervalues():
            cost += sum([o.cost() for o in orders])
        return

    def marketValue(self):
        mktval = 0.0
        for inst, orders in self.positions.iteritems():
            mktval += inst.marketPrice * sum([o.amountMatched for o in orders])
        return mktval
Exemplo n.º 8
0
class Room( Persistent, RoomBase, Fossilizable ):
    """
    ZODB specific implementation.

    For documentation of methods see base class.
    """

    fossilizes(IRoomMapFossil, IRoomCalendarFossil)

    __dalManager = Factory.getDALManager()
    vcList = []

    def __init__(self):
        RoomBase.__init__( self )
        self.customAtts = PersistentMapping()
        self.avaibleVC = []
        self._nonBookableDates = []

    def getNonBookableDates(self):
        try:
            if self._nonBookableDates:
                pass
        except AttributeError:
            self._nonBookableDates = []
            self._p_changed = 1
        return self._nonBookableDates

    def addNonBookableDate(self, udate):
        self._nonBookableDates.append(udate)
        self._p_changed = 1

    def addNonBookableDateFromParams(self, params):
        nbd = NonBookableDate(params["startDate"], params["endDate"])
        self._nonBookableDates.append(nbd)
        self._p_changed = 1

    def clearNonBookableDates(self):
        self._nonBookableDates = []
        self._p_changed = 1

    def isNonBookableDay(self, day):
        for nbd in self.getNonBookableDates():
            if nbd.doesDayOverlap(day):
                return True
        return False

    def getBlockedDay(self, day):
        blockings = Factory.newRoomBlocking().getByDate(day)
        for bl in blockings:
            rbl = bl.getBlockedRoom(self)
            if rbl and rbl.active is not False:
                return rbl
        return None

    def setAvailableVC(self, avc):
        self.avaibleVC = avc

    def getAvailableVC(self):
        try:
            return self.avaibleVC
        except:
            self.avaibleVC = []
        return self.avaibleVC

    @staticmethod
    def getRoot():
        return Room.__dalManager.getRoot(_ROOMS)

    def getAllManagers(self):
        managers = set([self.getResponsible()])
        if self.customAtts.get('Simba List'):
            groups = GroupHolder().match({'name': self.customAtts['Simba List']},
                                         exact=True, forceWithoutExtAuth=True)
            if not groups:
                groups = GroupHolder().match({'name': self.customAtts['Simba List']}, exact=True)
            if groups and len(groups) == 1:
                managers |= set(groups[0].getMemberList())
        return list(managers)

    def insert( self ):
        """ Documentation in base class. """
        RoomBase.insert( self )
        roomsBTree = Room.getRoot()
        # Ensure ID
        if self.id == None:
            # Maximum ID + 1
            if len( roomsBTree ) > 0:
                self.id = roomsBTree.maxKey() + 1
            else:
                self.id = 1 # Can not use maxKey for 1st record in a tree
        # Add self to the BTree
        roomsBTree[self.id] = self
        Catalog.getIdx('user_room').index_obj(self.guid)

    def update( self ):
        """ Documentation in base class. """
        RoomBase.update( self )

        # Check Simba mailing list
        listName = self.customAtts.get( 'Simba List' )
        if listName:
            from MaKaC.user import GroupHolder
            groups = GroupHolder().match( { 'name': listName }, forceWithoutExtAuth = True )
            if not groups:
                groups = GroupHolder().match( { 'name': listName } )
            if not groups:
                self.customAtts['Simba List'] = 'Error: unknown mailing list'

        # reindex - needed due to possible manager changes
        # super slow, though...
        Catalog.getIdx('user_room').unindex_obj(self.guid)
        Catalog.getIdx('user_room').index_obj(self.guid)

        self._p_changed = True

    def remove( self ):
        """ Documentation in base class. """
        RoomBase.remove( self )
        roomsBTree = Room.getRoot()
        del roomsBTree[self.id]
        Catalog.getIdx('user_room').unindex_obj(self.guid)

    @classmethod
    def isAvatarResponsibleForRooms(cls, avatar):
        return Catalog.getIdx('user_room').get(avatar.getId()) is not None

    @classmethod
    def getUserRooms(cls, avatar):
        return Catalog.getIdx('user_room').get(avatar.getId())

    # Typical actions
    @staticmethod
    def getRooms( *args, **kwargs ):
        """ Documentation in base class. """

        roomsBTree = Room.getRoot()
        location = kwargs.get( 'location' )

        if kwargs.get( 'allFast' ) == True:
            return [ room for room in roomsBTree.values() if room.isActive and (not location or room.locationName == location) ]

        if kwargs.get( 'reallyAllFast' ) == True:
            return [ room for room in roomsBTree.values() if (not location or room.locationName == location) ]

        if len( kwargs ) == 0:
            ret_lst = []
            for room in roomsBTree.values():
                ret_lst.append( room )

        roomID = kwargs.get( 'roomID' )
        roomName = kwargs.get( 'roomName' )
        roomEx = kwargs.get( 'roomExample' )
        resvEx = kwargs.get( 'resvExample' )
        freeText = kwargs.get( 'freeText' )
        available = kwargs.get( 'available' )
        countOnly = kwargs.get( 'countOnly' )
        minCapacity = kwargs.get( 'minCapacity' )
        location = kwargs.get( 'location' )
        ownedBy = kwargs.get( 'ownedBy' )
        customAtts = kwargs.get( 'customAtts' )
#        responsibleID = kwargs.get( 'responsibleID' )
        pendingBlockings = kwargs.get( 'pendingBlockings' )

        ret_lst = []
        counter = 0
        if roomID != None:
            return roomsBTree.get( roomID )
        if roomName != None:
            for room in roomsBTree.itervalues():
                if room.name == roomName:
                    if location == None or room.locationName == location:
                        return room
            return None

        for room in roomsBTree.itervalues():
            # Apply all conditions =========
            if location != None:
                if room.locationName != location:
                    continue
            if roomEx != None:
                if not qbeMatch( roomEx, room, Room.__attrSpecialEqual, minCapacity = minCapacity ):
                    continue
                if not room.__hasEquipment( roomEx.getEquipment() ):
                    continue
            if freeText != None:
                if not room.__hasFreeText( freeText.split() ):
                    continue
            if resvEx != None:
                resvEx.room = room
                aval = room.isAvailable( resvEx )
                if aval != available:
                    continue
                blockState = resvEx.getBlockingConflictState(ContextManager.get('currentUser'))
                if blockState == 'active':
                    continue
                elif blockState == 'pending' and pendingBlockings:
                    continue
            if ownedBy != None:
                if not room.isOwnedBy( ownedBy ):
                    continue
            if customAtts is not None:
                if not hasattr(room, "customAtts"):
                    continue
                discard = False
                for condition in customAtts:
                    attName = condition["name"]
                    allowEmpty = condition.get("allowEmpty", False)
                    filter = condition.get("filter", None)
                    if not attName in room.customAtts:
                        discard = True
                        break
                    elif not allowEmpty and str(room.customAtts[attName]).strip() == "":
                        discard = True
                        break
                    elif not filter(room.customAtts[attName]):
                        discard = True
                        break
                if discard:
                    continue

            # All conditions are met: add room to the results
            counter += 1
            if not countOnly:
                ret_lst.append( room )

        #print "Found %d rooms." % counter
        if countOnly:
            return counter
        else:
            return ret_lst

    # Statistics ====================================

    @staticmethod
    def countRooms( *args, **kwargs ):
        """ Documentation in base class. """
        kwargs['countOnly'] = True
        return Room.getRooms( **kwargs )

    @staticmethod
    def getNumberOfRooms( *args, **kwargs ):
        """ Documentation in base class. """
        location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName )
        return Room.countRooms( location = location )

    @staticmethod
    def getNumberOfActiveRooms( *args, **kwargs ):
        """ Documentation in base class. """
        location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName )
        room = Factory.newRoom()
        room.isActive = True
        return Room.countRooms( roomExample = room, location = location )

    @staticmethod
    def getNumberOfReservableRooms( *args, **kwargs ):
        """ Documentation in base class. """
        location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName )
        room = Factory.newRoom()
        room.isReservable = True
        room.isActive = True
        return Room.countRooms( roomExample = room, location = location )

    def getLocationName( self ):
        #from MaKaC.plugins.RoomBooking.default.factory import Factory
        #return Factory.locationName
        return self._locationName

    def setLocationName( self, locationName ):
        self._locationName = locationName

    def savePhoto( self, photoPath ):
        filePath = Config.getInstance().getRoomPhotosDir()
        fileName = self._doGetPhotoId( force = True ) + ".jpg"
        try: os.makedirs( filePath )
        except: pass
        fullPath = os.path.join( filePath, fileName )

        f = open( fullPath, "wb" )
        f.write( photoPath.file.read() )
        f.close()

    def saveSmallPhoto( self, photoPath ):
        filePath = Config.getInstance().getRoomSmallPhotosDir()
        fileName = self._doGetPhotoId( force = True ) + ".jpg"
        try: os.makedirs( filePath )
        except: pass
        fullPath = os.path.join( filePath, fileName )

        f = open( fullPath, "wb" )
        f.write( photoPath.file.read() )
        f.close()


    # ==== Private ===================================================

    def _getSafeLocationName( self ):
        if self.locationName == None:
            return None
        s = ""
        for i in xrange( 0, len( self.locationName ) ):
            code = ord( self.locationName[i] )
            if ( code in xrange( ord( 'a' ), ord( 'z' ) + 1 ) ) or \
               ( code in xrange( ord( 'A' ), ord( 'Z' ) + 1 ) ) or \
               ( code in xrange( ord( '0' ), ord( '9' ) + 1 ) ):
                # Valid
                s += self.locationName[i]
            else:
                s += '_' # Replace all other characters with underscore
        return s

    def _doGetPhotoId( self, force = False ):
        photoId = "%s-%s-%s-%s" % ( str( self._getSafeLocationName() ), str( self.building ).strip(), str( self.floor ).strip(), str( self.roomNr ).strip() )

        filePath = Config.getInstance().getRoomPhotosDir()
        fileName = photoId + ".jpg"
        fullPath = os.path.join( filePath, fileName )
        from os.path import exists
        if exists( fullPath ) or force:
            return photoId
        else:
            return None

    def _doSetPhotoId( self ):
        """
        For this plugin, photoId is always composed of location-building-floor-room.jpg
        """
        pass

    def __hasFreeText( self, freeTextList ):
        # OR
        for freeText in freeTextList:
            freeText = freeText.lower()
            if self.__hasOneFreeText( freeText ):
                return True
        return False

    def __hasOneFreeText( self, freeText ):
        # Look for freeText in all string and int attributes
        for attrName in dir( self ):
            if attrName[0] == '_':
                continue
            attrType = eval( 'self.' + attrName + '.__class__.__name__' )
            if attrType == 'str':
                attrVal = eval( 'self.' + attrName )
                if attrVal.lower().find( freeText ) != -1:
                    return True

        # Look for freeText in equipment
        if self.__hasEquipment( [ freeText ] ):
            return True

        # Look for freeText in responsible
        if self.responsibleId != None:
            user = self.getResponsible();
            if freeText in user.getFullName().lower()  or  freeText in user.getEmail().lower():
                return True

        # Look for freeText in custom attributes
        for value in self.customAtts.itervalues():
            if value and ( freeText in value.lower() ):
                return True

        # Not found
        return False

    @staticmethod
    def __goodCapacity( val1, val2, minCapacity = None ):
        # Difference in capacity less than 20%
        if val1 < 1: val1 = 1

        if not minCapacity:
            return abs( val1 - val2 ) / float( val1 ) <= 0.2
        else:
            return val2 > val1

    @classmethod
    def __attrSpecialEqual( cls, attrName, exampleVal, candidateVal, **kwargs ):
        if attrName in ( 'guid', 'locationName', 'name', 'photoId', 'needsAVCSetup' ):
            return True # Skip by stating they match
        if attrName in ( 'responsibleId', 'responsibleID' ):
            return exampleVal == candidateVal # Just exact string matching
        if attrName[0:7] == 'verbose':
            return True
        if attrName.find( 'capacity' ) != -1:
            minCapacity = kwargs.get( 'minCapacity' )
            return cls.__goodCapacity( exampleVal, candidateVal, minCapacity )
        if attrName == 'customAtts':
            # Check if all values in exampleVal are contained
            # in corresponding values of candidateVal
            for k, v in exampleVal.iteritems():
                if v: # If value is specified
                    if candidateVal.get( k ) == None:
                        # Candidate does not have the attribute
                        return False
                    if not ( v in candidateVal[k] ):
                        # Candidate's attribute value does not match example
                        return False
            return True
        return None

    def __hasEquipment( self, requiredEquipmentList ):
        iHave = self.getEquipment()
        for reqEq in requiredEquipmentList:
            have = False
            for myEq in iHave:
                if myEq.lower().find( reqEq.lower() ) != -1:
                    have = True
                    break
            if not have:
                return False
        return True

    def getBookingUrl(self):
        """ Room booking URL """
        return str(urlHandlers.UHRoomBookingBookingForm.getURL(target=self))

    def getDetailsUrl(self):
        """ Room details URL """
        return str(urlHandlers.UHRoomBookingRoomDetails.getURL(target=self))

    def getMarkerDescription(self):
        """ Room description for the map marker """
        infos = []
        if self.capacity:
            infos.append("%s %s" % (self.capacity , _("people")))
        if self.isReservable:
            infos.append(_("public"))
        else:
            infos.append(_("private"))
        if self.resvsNeedConfirmation:
            infos.append(_("needs confirmation"))
        else:
            infos.append(_("auto-confirmation"))
        if self.needsAVCSetup:
            infos.append(_("video conference"))
        return ", ".join(infos)

    def getTipPhotoURL(self):
        """ URL of the tip photo of the room """
        from MaKaC.webinterface.urlHandlers import UHRoomPhoto
        photoId = self._doGetPhotoId()
        if not photoId:
            photoId = "NoPhoto"
        return str(UHRoomPhoto.getURL(photoId))

    def getIsAutoConfirm(self):
        """ Has the room auto-confirmation of schedule? """
        return not self.resvsNeedConfirmation

    locationName = property( getLocationName, setLocationName )
Exemplo n.º 9
0
class Room( Persistent, RoomBase, Fossilizable ):
    """
    ZODB specific implementation.

    For documentation of methods see base class.
    """

    fossilizes(IRoomMapFossil, IRoomCalendarFossil)

    __dalManager = Factory.getDALManager()
    vcList = []

    def __init__(self):
        RoomBase.__init__( self )
        self.customAtts = PersistentMapping()
        self.avaibleVC = []
        self._nonBookableDates = []

    def getNonBookableDates(self):
        try:
            if self._nonBookableDates:
                pass
        except AttributeError:
            self._nonBookableDates = []
            self._p_changed = 1
        return self._nonBookableDates

    def addNonBookableDate(self, udate):
        self._nonBookableDates.append(udate)
        self._p_changed = 1

    def addNonBookableDateFromParams(self, params):
        nbd = NonBookableDate(params["startDate"], params["endDate"])
        self._nonBookableDates.append(nbd)
        self._p_changed = 1

    def clearNonBookableDates(self):
        self._nonBookableDates = []
        self._p_changed = 1

    def isNonBookableDay(self, day):
        for nbd in self.getNonBookableDates():
            if nbd.doesDayOverlap(day):
                return True
        return False

    def getBlockedDay(self, day):
        blockings = Factory.newRoomBlocking().getByDate(day)
        for bl in blockings:
            rbl = bl.getBlockedRoom(self)
            if rbl and rbl.active is not False:
                return rbl
        return None

    def setAvailableVC(self, avc):
        self.avaibleVC = avc

    def getAvailableVC(self):
        try:
            return self.avaibleVC
        except:
            self.avaibleVC = []
        return self.avaibleVC

    @staticmethod
    def getRoot():
        return Room.__dalManager.getRoot(_ROOMS)

    def getAllManagers(self):
        managers = set([self.getResponsible()])
        if self.customAtts.get('Simba List'):
            groups = GroupHolder().match({'name': self.customAtts['Simba List']},
                                         exact=True, forceWithoutExtAuth=True)
            if not groups:
                groups = GroupHolder().match({'name': self.customAtts['Simba List']}, exact=True)
            if groups and len(groups) == 1:
                managers |= set(groups[0].getMemberList())
        return list(managers)

    def insert( self ):
        """ Documentation in base class. """
        RoomBase.insert( self )
        roomsBTree = Room.getRoot()
        # Ensure ID
        if self.id == None:
            # Maximum ID + 1
            if len( roomsBTree ) > 0:
                self.id = roomsBTree.maxKey() + 1
            else:
                self.id = 1 # Can not use maxKey for 1st record in a tree
        # Add self to the BTree
        roomsBTree[self.id] = self
        Catalog.getIdx('user_room').index_obj(self.guid)

    def update( self ):
        """ Documentation in base class. """
        RoomBase.update( self )

        # Check Simba mailing list
        listName = self.customAtts.get( 'Simba List' )
        if listName:
            from MaKaC.user import GroupHolder
            groups = GroupHolder().match( { 'name': listName }, forceWithoutExtAuth = True )
            if not groups:
                groups = GroupHolder().match( { 'name': listName } )
            if not groups:
                self.customAtts['Simba List'] = 'Error: unknown mailing list'

        # reindex - needed due to possible manager changes
        # super slow, though...
        Catalog.getIdx('user_room').unindex_obj(self.guid)
        Catalog.getIdx('user_room').index_obj(self.guid)

        self._p_changed = True

    def remove( self ):
        """ Documentation in base class. """
        RoomBase.remove( self )
        roomsBTree = Room.getRoot()
        del roomsBTree[self.id]
        if Catalog.getIdx('user_room').has_obj(self.guid):
            Catalog.getIdx('user_room').unindex_obj(self.guid)

    @classmethod
    def isAvatarResponsibleForRooms(cls, avatar):
        return Catalog.getIdx('user_room').get(avatar.getId()) is not None

    @classmethod
    def getUserRooms(cls, avatar):
        return Catalog.getIdx('user_room').get(avatar.getId())

    # Typical actions
    @staticmethod
    def getRooms( *args, **kwargs ):
        """ Documentation in base class. """

        roomsBTree = Room.getRoot()
        location = kwargs.get( 'location' )

        if kwargs.get( 'allFast' ) == True:
            return [ room for room in roomsBTree.values() if room.isActive and (not location or room.locationName == location) ]

        if kwargs.get( 'reallyAllFast' ) == True:
            return [ room for room in roomsBTree.values() if (not location or room.locationName == location) ]

        if len( kwargs ) == 0:
            ret_lst = []
            for room in roomsBTree.values():
                ret_lst.append( room )

        roomID = kwargs.get( 'roomID' )
        roomName = kwargs.get( 'roomName' )
        roomEx = kwargs.get( 'roomExample' )
        resvEx = kwargs.get( 'resvExample' )
        freeText = kwargs.get( 'freeText' )
        available = kwargs.get( 'available' )
        countOnly = kwargs.get( 'countOnly' )
        minCapacity = kwargs.get( 'minCapacity' )
        location = kwargs.get( 'location' )
        ownedBy = kwargs.get( 'ownedBy' )
        customAtts = kwargs.get( 'customAtts' )
#        responsibleID = kwargs.get( 'responsibleID' )
        pendingBlockings = kwargs.get( 'pendingBlockings' )

        ret_lst = []
        counter = 0
        if roomID != None:
            return roomsBTree.get( roomID )
        if roomName != None:
            for room in roomsBTree.itervalues():
                if room.name == roomName:
                    if location == None or room.locationName == location:
                        return room
            return None

        for room in roomsBTree.itervalues():
            # Apply all conditions =========
            if location != None:
                if room.locationName != location:
                    continue
            if roomEx != None:
                if not qbeMatch( roomEx, room, Room.__attrSpecialEqual, minCapacity = minCapacity ):
                    continue
                if not room.__hasEquipment( roomEx.getEquipment() ):
                    continue
            if freeText != None:
                if not room.__hasFreeText( freeText.split() ):
                    continue
            if resvEx != None:
                resvEx.room = room
                aval = room.isAvailable( resvEx )
                if aval != available:
                    continue
                blockState = resvEx.getBlockingConflictState(ContextManager.get('currentUser'))
                if blockState == 'active':
                    continue
                elif blockState == 'pending' and pendingBlockings:
                    continue
            if ownedBy != None:
                if not room.isOwnedBy( ownedBy ):
                    continue
            if customAtts is not None:
                if not hasattr(room, "customAtts"):
                    continue
                discard = False
                for condition in customAtts:
                    attName = condition["name"]
                    allowEmpty = condition.get("allowEmpty", False)
                    filter = condition.get("filter", None)
                    if not attName in room.customAtts:
                        discard = True
                        break
                    elif not allowEmpty and str(room.customAtts[attName]).strip() == "":
                        discard = True
                        break
                    elif not filter(room.customAtts[attName]):
                        discard = True
                        break
                if discard:
                    continue

            # All conditions are met: add room to the results
            counter += 1
            if not countOnly:
                ret_lst.append( room )

        #print "Found %d rooms." % counter
        if countOnly:
            return counter
        else:
            return ret_lst

    # Statistics ====================================

    @staticmethod
    def countRooms( *args, **kwargs ):
        """ Documentation in base class. """
        kwargs['countOnly'] = True
        return Room.getRooms( **kwargs )

    @staticmethod
    def getNumberOfRooms( *args, **kwargs ):
        """ Documentation in base class. """
        location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName )
        return Room.countRooms( location = location )

    @staticmethod
    def getNumberOfActiveRooms( *args, **kwargs ):
        """ Documentation in base class. """
        location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName )
        room = Factory.newRoom()
        room.isActive = True
        return Room.countRooms( roomExample = room, location = location )

    @staticmethod
    def getNumberOfReservableRooms( *args, **kwargs ):
        """ Documentation in base class. """
        location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName )
        room = Factory.newRoom()
        room.isReservable = True
        room.isActive = True
        return Room.countRooms( roomExample = room, location = location )

    def getLocationName( self ):
        #from MaKaC.plugins.RoomBooking.default.factory import Factory
        #return Factory.locationName
        return self._locationName

    def setLocationName( self, locationName ):
        self._locationName = locationName

    def savePhoto( self, photoPath ):
        filePath = Config.getInstance().getRoomPhotosDir()
        fileName = self._doGetPhotoId( force = True ) + ".jpg"
        try: os.makedirs( filePath )
        except: pass
        fullPath = os.path.join( filePath, fileName )

        f = open( fullPath, "wb" )
        f.write( photoPath.file.read() )
        f.close()

    def saveSmallPhoto( self, photoPath ):
        filePath = Config.getInstance().getRoomSmallPhotosDir()
        fileName = self._doGetPhotoId( force = True ) + ".jpg"
        try: os.makedirs( filePath )
        except: pass
        fullPath = os.path.join( filePath, fileName )

        f = open( fullPath, "wb" )
        f.write( photoPath.file.read() )
        f.close()


    # ==== Private ===================================================

    def _getSafeLocationName( self ):
        if self.locationName == None:
            return None
        s = ""
        for i in xrange( 0, len( self.locationName ) ):
            code = ord( self.locationName[i] )
            if ( code in xrange( ord( 'a' ), ord( 'z' ) + 1 ) ) or \
               ( code in xrange( ord( 'A' ), ord( 'Z' ) + 1 ) ) or \
               ( code in xrange( ord( '0' ), ord( '9' ) + 1 ) ):
                # Valid
                s += self.locationName[i]
            else:
                s += '_' # Replace all other characters with underscore
        return s

    def _doGetPhotoId( self, force = False ):
        photoId = "%s-%s-%s-%s" % ( str( self._getSafeLocationName() ), str( self.building ).strip(), str( self.floor ).strip(), str( self.roomNr ).strip() )

        filePath = Config.getInstance().getRoomPhotosDir()
        fileName = photoId + ".jpg"
        fullPath = os.path.join( filePath, fileName )
        from os.path import exists
        if exists( fullPath ) or force:
            return photoId
        else:
            return None

    def _doSetPhotoId( self ):
        """
        For this plugin, photoId is always composed of location-building-floor-room.jpg
        """
        pass

    def __hasFreeText( self, freeTextList ):
        # OR
        for freeText in freeTextList:
            freeText = freeText.lower()
            if self.__hasOneFreeText( freeText ):
                return True
        return False

    def __hasOneFreeText( self, freeText ):
        # Look for freeText in all string and int attributes
        for attrName in dir( self ):
            if attrName[0] == '_':
                continue
            attrType = eval( 'self.' + attrName + '.__class__.__name__' )
            if attrType == 'str':
                attrVal = eval( 'self.' + attrName )
                if attrVal.lower().find( freeText ) != -1:
                    return True

        # Look for freeText in equipment
        if self.__hasEquipment( [ freeText ] ):
            return True

        # Look for freeText in responsible
        if self.responsibleId != None:
            user = self.getResponsible();
            if freeText in user.getFullName().lower()  or  freeText in user.getEmail().lower():
                return True

        # Look for freeText in custom attributes
        for value in self.customAtts.itervalues():
            if value and ( freeText in value.lower() ):
                return True

        # Not found
        return False

    @staticmethod
    def __goodCapacity( val1, val2, minCapacity = None ):
        # Difference in capacity less than 20%
        if val1 < 1: val1 = 1

        if not minCapacity:
            return abs( val1 - val2 ) / float( val1 ) <= 0.2
        else:
            return val2 > val1

    @classmethod
    def __attrSpecialEqual( cls, attrName, exampleVal, candidateVal, **kwargs ):
        if attrName in ( 'guid', 'locationName', 'name', 'photoId', 'needsAVCSetup' ):
            return True # Skip by stating they match
        if attrName in ( 'responsibleId', 'responsibleID' ):
            return exampleVal == candidateVal # Just exact string matching
        if attrName[0:7] == 'verbose':
            return True
        if attrName.find( 'capacity' ) != -1:
            minCapacity = kwargs.get( 'minCapacity' )
            return cls.__goodCapacity( exampleVal, candidateVal, minCapacity )
        if attrName == 'customAtts':
            # Check if all values in exampleVal are contained
            # in corresponding values of candidateVal
            for k, v in exampleVal.iteritems():
                if v: # If value is specified
                    if candidateVal.get( k ) == None:
                        # Candidate does not have the attribute
                        return False
                    if not ( v in candidateVal[k] ):
                        # Candidate's attribute value does not match example
                        return False
            return True
        return None

    def __hasEquipment( self, requiredEquipmentList ):
        iHave = self.getEquipment()
        for reqEq in requiredEquipmentList:
            have = False
            for myEq in iHave:
                if myEq.lower().find( reqEq.lower() ) != -1:
                    have = True
                    break
            if not have:
                return False
        return True

    def getBookingUrl(self):
        """ Room booking URL """
        return str(urlHandlers.UHRoomBookingBookingForm.getURL(target=self))

    def getDetailsUrl(self):
        """ Room details URL """
        return str(urlHandlers.UHRoomBookingRoomDetails.getURL(target=self))

    def getMarkerDescription(self):
        """ Room description for the map marker """
        infos = []
        if self.capacity:
            infos.append("%s %s" % (self.capacity , _("people")))
        if self.isReservable:
            infos.append(_("public"))
        else:
            infos.append(_("private"))
        if self.resvsNeedConfirmation:
            infos.append(_("needs confirmation"))
        else:
            infos.append(_("auto-confirmation"))
        if self.needsAVCSetup:
            infos.append(_("video conference"))
        return ", ".join(infos)

    def getTipPhotoURL(self):
        """ URL of the tip photo of the room """
        from MaKaC.webinterface.urlHandlers import UHRoomPhoto
        photoId = self._doGetPhotoId()
        if not photoId:
            photoId = "NoPhoto"
        return str(UHRoomPhoto.getURL(photoId))

    def getIsAutoConfirm(self):
        """ Has the room auto-confirmation of schedule? """
        return not self.resvsNeedConfirmation

    locationName = property( getLocationName, setLocationName )
Exemplo n.º 10
0
class Room( Persistent, RoomBase ):
    """ 
    ZODB specific implementation. 
    
    For documentation of methods see base class.
    """

    __dalManager = Factory.getDALManager()
    vcList = []

    def __init__(self):
        RoomBase.__init__( self )
        self.customAtts = PersistentMapping()
        self.avaibleVC = []
    
    def setAvailableVC(self, avc):
        self.avaibleVC = avc
    
    def getAvailableVC(self):
        try:
            return self.avaibleVC
        except:
            self.avaibleVC = []
        return self.avaibleVC

    @staticmethod
    def getRoot():
        return Room.__dalManager.getRoot(_ROOMS)
    
    def insert( self ):
        """ Documentation in base class. """
        RoomBase.insert( self )
        roomsBTree = Room.getRoot()
        # Ensure ID
        if self.id == None:
            # Maximum ID + 1
            if len( roomsBTree ) > 0:
                self.id = roomsBTree.maxKey() + 1
            else:
                self.id = 1 # Can not use maxKey for 1st record in a tree
        # Add self to the BTree
        roomsBTree[self.id] = self 
    
    def update( self ):
        """ Documentation in base class. """
        RoomBase.update( self )
        
        # Check Simba mailing list
        listName = self.customAtts.get( 'Simba List' )
        if listName:
            from MaKaC.user import GroupHolder
            groups = GroupHolder().match( { 'name': listName }, forceWithoutExtAuth = True )
            if not groups:
                groups = GroupHolder().match( { 'name': listName } )
            if not groups:
                self.customAtts['Simba List'] = 'Error: unknown mailing list'
        
        self._p_changed = True
    
    def remove( self ):
        """ Documentation in base class. """
        RoomBase.remove( self )
        roomsBTree = Room.getRoot()
        del roomsBTree[self.id]
        from MaKaC.user import AvatarHolder
        AvatarHolder().invalidateRoomManagerIdList()
    
    # Typical actions
    @staticmethod
    def getRooms( *args, **kwargs ): 
        """ Documentation in base class. """

        roomsBTree = Room.getRoot()
        location = kwargs.get( 'location' )

        if kwargs.get( 'allFast' ) == True:
            return [ room for room in roomsBTree.values() if room.isActive and (not location or room.locationName == location) ]

        if kwargs.get( 'reallyAllFast' ) == True:
            return [ room for room in roomsBTree.values() if (not location or room.locationName == location) ]
        
        if len( kwargs ) == 0:
            ret_lst = []
            for room in roomsBTree.values():
                ret_lst.append( room )

        roomID = kwargs.get( 'roomID' )
        roomName = kwargs.get( 'roomName' )
        roomEx = kwargs.get( 'roomExample' )
        resvEx = kwargs.get( 'resvExample' )
        freeText = kwargs.get( 'freeText' )
        available = kwargs.get( 'available' )
        countOnly = kwargs.get( 'countOnly' )
        minCapacity = kwargs.get( 'minCapacity' )
        location = kwargs.get( 'location' )
        ownedBy = kwargs.get( 'ownedBy' )
        customAtts = kwargs.get( 'customAtts' )
#        responsibleID = kwargs.get( 'responsibleID' )
        
        ret_lst = []
        counter = 0
        if roomID != None:
            return roomsBTree.get( roomID )
        if roomName != None:
            for room in roomsBTree.itervalues():
                if room.name == roomName:
                    if location == None or room.locationName == location:
                        return room
            return None
        
        for room in roomsBTree.itervalues():
            # Apply all conditions =========
            if location != None:
                if room.locationName != location:
                    continue            
            if roomEx != None:
                if not qbeMatch( roomEx, room, Room.__attrSpecialEqual, minCapacity = minCapacity ):
                    continue
                if not room.__hasEquipment( roomEx.getEquipment() ):
                    continue
            if freeText != None:
                if not room.__hasFreeText( freeText.split() ):
                    continue
            if resvEx != None:
                resvEx.room = room
                aval = room.isAvailable( resvEx )
                if aval != available:
                    continue
            if ownedBy != None:
                if not room.isOwnedBy( ownedBy ):
                    continue
            if customAtts is not None:
                if not hasattr(room, "customAtts"):
                    continue
                discard = False
                for condition in customAtts:
                    attName = condition["name"]
                    allowEmpty = condition.get("allowEmpty", False)
                    filter = condition.get("filter", None)
                    if not attName in room.customAtts:
                        discard = True
                        break
                    elif not allowEmpty and str(room.customAtts[attName]).strip() == "":
                        discard = True
                        break
                    elif not filter(room.customAtts[attName]):
                        discard = True
                        break
                if discard:
                    continue
            
            # All conditions are met: add room to the results
            counter += 1
            if not countOnly:
                ret_lst.append( room )

        #print "Found %d rooms." % counter
        if countOnly:
            return counter
        else:
            return ret_lst

    # Statistics ====================================

    @staticmethod
    def countRooms( *args, **kwargs ):
        """ Documentation in base class. """
        kwargs['countOnly'] = True
        return Room.getRooms( **kwargs )

    @staticmethod
    def getNumberOfRooms( *args, **kwargs ):
        """ Documentation in base class. """
        location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName )
        return Room.countRooms( location = location )
    
    @staticmethod
    def getNumberOfActiveRooms( *args, **kwargs ):
        """ Documentation in base class. """
        location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName )
        room = Factory.newRoom()
        room.isActive = True
        return Room.countRooms( roomExample = room, location = location )

    @staticmethod
    def getNumberOfReservableRooms( *args, **kwargs ):
        """ Documentation in base class. """
        location = kwargs.get( 'location', Location.getDefaultLocation().friendlyName )
        room = Factory.newRoom()
        room.isReservable = True
        room.isActive = True
        return Room.countRooms( roomExample = room, location = location )
    
    def getLocationName( self ):
        #from MaKaC.plugins.RoomBooking.default.factory import Factory
        #return Factory.locationName
        return self._locationName
    
    def setLocationName( self, locationName ):
        self._locationName = locationName

    def savePhoto( self, photoPath ):
        filePath = Config.getInstance().getRoomPhotosDir()
        fileName = self._doGetPhotoId( force = True ) + ".jpg"
        try: os.makedirs( filePath )
        except: pass
        fullPath = os.path.join( filePath, fileName )

        f = open( fullPath, "wb" )
        f.write( photoPath.file.read() )
        f.close()
    
    def saveSmallPhoto( self, photoPath ):
        filePath = Config.getInstance().getRoomSmallPhotosDir()
        fileName = self._doGetPhotoId( force = True ) + ".jpg"
        try: os.makedirs( filePath )
        except: pass
        fullPath = os.path.join( filePath, fileName )

        f = open( fullPath, "wb" )
        f.write( photoPath.file.read() )
        f.close()

    
    # ==== Private ===================================================

    def _getSafeLocationName( self ):
        if self.locationName == None:
            return None
        s = ""
        for i in xrange( 0, len( self.locationName ) ):
            code = ord( self.locationName[i] )
            if ( code in xrange( ord( 'a' ), ord( 'z' ) + 1 ) ) or \
               ( code in xrange( ord( 'A' ), ord( 'Z' ) + 1 ) ) or \
               ( code in xrange( ord( '0' ), ord( '9' ) + 1 ) ):
                # Valid
                s += self.locationName[i]
            else:
                s += '_' # Replace all other characters with underscore
        return s

    def _doGetPhotoId( self, force = False ):
        photoId = "%s-%s-%s-%s" % ( str( self._getSafeLocationName() ), str( self.building ).strip(), str( self.floor ).strip(), str( self.roomNr ).strip() )
        
        filePath = Config.getInstance().getRoomPhotosDir()
        fileName = photoId + ".jpg"
        fullPath = os.path.join( filePath, fileName )
        from os.path import exists
        if exists( fullPath ) or force:
            return photoId
        else:
            return None

    def _doSetPhotoId( self ):
        """
        For this plugin, photoId is always composed of location-building-floor-room.jpg
        """
        pass

    def __hasFreeText( self, freeTextList ):
        # OR
        for freeText in freeTextList:
            freeText = freeText.lower()
            if self.__hasOneFreeText( freeText ):
                return True
        return False
    
    def __hasOneFreeText( self, freeText ):
        # Look for freeText in all string and int attributes
        for attrName in dir( self ):
            if attrName[0] == '_': 
                continue 
            attrType = eval( 'self.' + attrName + '.__class__.__name__' )
            if attrType == 'str': 
                attrVal = eval( 'self.' + attrName )
                if attrVal.lower().find( freeText ) != -1:
                    return True

        # Look for freeText in equipment
        if self.__hasEquipment( [ freeText ] ):
            return True
        
        # Look for freeText in responsible
        if self.responsibleId != None:
            user = self.getResponsible();
            if freeText in user.getFullName().lower()  or  freeText in user.getEmail().lower():
                return True
        
        # Look for freeText in custom attributes
        for value in self.customAtts.itervalues():
            if value and ( freeText in value.lower() ):
                return True
        
        # Not found
        return False
        
    @staticmethod
    def __goodCapacity( val1, val2, minCapacity = None ):
        # Difference in capacity less than 20%
        if val1 < 1: val1 = 1
        
        if not minCapacity:
            return abs( val1 - val2 ) / float( val1 ) <= 0.2
        else:
            return val2 > val1

    @classmethod
    def __attrSpecialEqual( cls, attrName, exampleVal, candidateVal, **kwargs ):
        if attrName in ( 'guid', 'locationName', 'name', 'photoId', 'needsAVCSetup' ):
            return True # Skip by stating they match
        if attrName in ( 'responsibleId', 'responsibleID' ):
            return exampleVal == candidateVal # Just exact string matching
        if attrName[0:7] == 'verbose':
            return True
        if attrName.find( 'capacity' ) != -1:
            minCapacity = kwargs.get( 'minCapacity' )
            return cls.__goodCapacity( exampleVal, candidateVal, minCapacity )
        if attrName == 'customAtts':
            # Check if all values in exampleVal are contained 
            # in corresponding values of candidateVal
            for k, v in exampleVal.iteritems():
                if v: # If value is specified
                    if candidateVal.get( k ) == None:
                        # Candidate does not have the attribute
                        return False
                    if not ( v in candidateVal[k] ):
                        # Candidate's attribute value does not match example
                        return False
            return True
        return None
        
    def __hasEquipment( self, requiredEquipmentList ):
        iHave = self.getEquipment()
        for reqEq in requiredEquipmentList:
            have = False
            for myEq in iHave:
                if myEq.lower().find( reqEq.lower() ) != -1:
                    have = True
                    break
            if not have:
                return False
        return True