'''
Created on Jul 30, 2014

@author: Mandy
'''
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QMessageBox
from EdgeItem import EdgeItem
from RoleNode import RoleNode, RoleCompactNode
from DirNode import DirNode
from UserNode import UserNode
import MyFunctions, rbacpolicy

class PolicyManager(object):

    def __init__(self, main):
        self.main = main
        self.mainMode = main.mode
        self.scene = main.scene
        self.sceneRight = main.sceneRight
        self.nullRoleNode = 'None'
        
    def addParentInRoleAdjmat(self, r, p):
        if r not in self.main.role_adjmat.keys():
            self.main.role_adjmat.update({r:rbacpolicy.makerolenode(parents=set([p]))})
        else:
            self.main.role_adjmat[r].parents.add(p)
            
    def addChildInRoleAdjmat(self, r, c):
        if r not in self.main.role_adjmat.keys():
            self.main.role_adjmat.update({r:rbacpolicy.makerolenode(children=set([c]))})
        else:
            self.main.role_adjmat[r].children.add(c)
            
    def deleteParentInRoleAdjmat(self, r, p):
#         print self.main.role_adjmat
        print r, p, self.main.role_adjmat[r].parents
        if r in self.main.role_adjmat.keys():
            self.main.role_adjmat[r].parents.remove(p)
        
    def deleteChildInRoleAdjmat(self, r, c):
        if r in self.main.role_adjmat.keys():
            self.main.role_adjmat[r].children.remove(c)
            
    def checkElementExistInList(self, element, listName):
        if element in listName:
            return True
        else:
            return False
        
    def findRoleNode(self, nodename, listInstance):
        for r in listInstance:
            if nodename == r.name:
                return r
        return None
    
    def findDirNode(self, nodename, listInstance):
        for r in listInstance:
            if nodename == r.dir:
                return r
        return None
    
    def intersectTwoSets(self, set1, set2):
        for e in set1:
            if e in set2:
                return True
        return False
    
    def removeTransitiveEdges(self, roleNodeList, implicitFlag):
        for r in roleNodeList:
            for ar in roleNodeList:
                if r in ar.possibleParentNodes:
                    if implicitFlag:
                        if self.intersectTwoSets(r.possibleChildrenNodes, ar.possibleParentNodes):
                            r.possibleChildrenNodes.remove(ar)
                            ar.possibleParentNodes.remove(r)
                            for e in self.main.scene.items():
                                if isinstance(e, EdgeItem) and e.type == EdgeItem.IMPLICIT_ROLE_CONN:
                                    if e.startItem == r and e.endItem == ar:
                                        self.main.scene.removeItem(e)
                                        del e
                    else:
                        if self.intersectTwoSets(r.childrenNodes, ar.parentNodes):
                            r.childrenNodes.remove(ar)
                            ar.parentNodes.remove(r)
                            for e in self.main.scene.items():
                                if isinstance(e, EdgeItem) and e.type == EdgeItem.ROLE_HIERARCH_CONN:
                                    if e.startItem == r and e.endItem == ar:
                                        self.main.scene.removeItem(e)
                                        del e
                        
        '''query functions'''
    def findAllChildrenRoleNodes(self, rolename):
        rolenode = None
        roles = set()
        for r in self.main.roleCompactNodes:
            if r.name == rolename:
                rolenode = r
                roles.add(rolenode)
        for c in rolenode.allChildrenNodes:
            roles.add(c)
        return  roles
    
    def findUserNamesForRoleWithInherit(self, rolename):
        rolenodes = self.findAllChildrenRoleNodes(rolename)
        users = set()
        for r in rolenodes:
            for key, value in self.main.user_role_mat.iteritems():
                if r.name in value:
                    users.add(key)
        return users 

    def fineUserNamesforRoleName(self, rolename):
        users = set()
        for key, value in self.main.user_role_mat.iteritems():
            if rolename in value:
                users.add(key)
        return users
    
    '''ALL_VIEWS'''       
    def createRoleNode(self, r):
        role = RoleNode(r, self.scene, self.main)
        self.main.roleNodes.append(role)
        if role not in self.scene.items():
            self.scene.addItem(role)
        return role
    
    def createRoleCompactNode(self, r):
        compactRole = RoleCompactNode(r, self.scene, self.main)
        self.main.roleCompactNodes.append(compactRole)
        if compactRole not in self.scene.items():
            self.scene.addItem(compactRole)
        return compactRole
    
    def createDirNode(self, d):
        dire = DirNode(d, self.sceneRight)
        self.main.dirNodes.append(dire)
        self.sceneRight.addItem(dire)
        return dire
    
    def computeNewDirPosInHierarchy(self, n):
        dirHier = self.main.dirNodesHierarchy
        dirNodeList = self.main.dirNodes
        dirHier = [dirHier[0]]
        for n in dirNodeList:
            n.parent = []
            n.children = []
        dirNodeList = sorted(dirNodeList, key=lambda x: len(x.dir.split('/')))
        for n in dirNodeList:
            for p in dirNodeList:
                dirList1 = p.dir.split('/')
                dirList2 = n.dir.split('/')
                dirList1 = filter(lambda a:a!= '', dirList1)
                dirList2 = filter(lambda a:a != '', dirList2)
                if p.dir != n.dir and MyFunctions.compareTwoLists(dirList1, dirList2):
                    if n.parent == []:
                        n.parent.append(p)
                    else:
                        parentList = n.parent[0].dir.split('/')
                        parentList = filter(lambda a:a!= '', parentList)
                        if len(parentList)<len(dirList1):
                            n.parent[0] = p
        for n in dirNodeList:
            for d in n.parent:
                d.children.append(n)
        tovisit = dirHier[0]
        while tovisit:
            nextlevel = set()
            for v in tovisit:
                nextlevel = nextlevel.union(set(v.children))
            tovisit = list(nextlevel)
            dirHier.append(tovisit)
            
        self.main.dirNodesHierarchy = dirHier
#         for i in xrange(0, len(self.main.dirNodesHierarchy)):
#             for n in self.main.dirNodesHierarchy[i]:
#                 print i, n.dir
#                 print 'parent'
#                 for p in n.parent:
#                     print p.dir
#                 print 'children'
#                 for c in n.children:
#                     print c.dir

    def moveDirNodeChildrenOneLevelUp(self, dirHier, node):
        children = node.children
        childrenHier = [node.children]
        index = MyFunctions.indexofSetInListcontainItem(node, dirHier)
        dirHier[index].remove(node)
        while children:
            tempLevel = set()
            for c in children:
                tempLevel = tempLevel.union(set(c.children))
            children = list(tempLevel)
            childrenHier.append(children)
        
        for i in xrange(len(childrenHier)):
            dirHier[index+i].extend(childrenHier[i])
            for c in childrenHier[i]:
                dirHier[index+i+1].remove(c)
                    
    def recomputeDirHierForNodeRemoval(self, node):
        dirHier = self.main.dirNodesHierarchy
        self.moveDirNodeChildrenOneLevelUp(dirHier, node)
        for c in node.children:
            c.parent = node.parent
        '''have to move every dir children one level up'''
        node.parent[0].children.remove(node)
        node.parent[0].children.extend(node.children)
        for d in self.main.dirNodes:
            self.main.computeSpec.getAllParentNodesForDirNode(d)
            
    def recomputeEdgeForDirHier(self):
        for e in self.sceneRight.items():
            if isinstance(e, EdgeItem):
                self.sceneRight.removeItem(e)
                del e
        for i in xrange(len(self.main.dirNodesHierarchy)):
            for j in self.main.dirNodesHierarchy[i]:
                for c in j.children:
                    edge = EdgeItem(EdgeItem.SEPARATE_DIR_CONN, j, c, self)
                    self.sceneRight.addItem(edge)
       
    def createUserNode(self, userName):
        usernode = UserNode(userName, self.main)
        self.main.userNodes.append(usernode)
        self.scene.addItem(usernode)
        self.randomlyPlaceUsernode(usernode)
        return usernode         
                              
    def createEdgeForRoleHier(self, r, child):
        edge = EdgeItem(EdgeItem.ROLE_HIERARCH_CONN, r, child, self.main)
        r.childrenNodes.add(child)
        child.parentNodes.add(r)
        r.children.add(child.name)
        child.parents.add(r.name)
        self.scene.addItem(edge)
        
    def createEdgeForRoleCompactHier(self, r, child):
        edgeCompact = EdgeItem(EdgeItem.SEPARATE_ROLE_CONN, r, child, self.main)
        #r.roleEdgeList.append(edgeCompact)
        r.childrenNodes.add(child)
        child.parentNodes.add(r)
        r.children.add(child.name)
        child.parents.add(r.name)

            
        self.scene.addItem(edgeCompact)
    
    def deleteEdgeItem(self, e, relatedNode1=None, relatedNode2=None, numEdges = 2):
        if isinstance(e, EdgeItem):
            if numEdges == 2:
                if e.startItem == relatedNode1 or e.endItem == relatedNode1 \
                    or e.startItem == relatedNode2 or e.endItem == relatedNode2:
                    self.scene.removeItem(e)
                    del e
            elif numEdges == 1:
                if e.startItem == relatedNode1 and e.endItem == relatedNode2\
                    or e.startItem == relatedNode2 and e.endItem == relatedNode1:
                    self.scene.removeItem(e)
                    del e
                
                    
    def deleteUserNodeForRoleNode(self, userNode, roleNode):
        self.scene.removeItem(userNode)
        self.main.userNodes.remove(userNode)
        self.main.userSet = set()
        for u in self.main.userNodes:
            self.main.userSet.add(u.name)
        self.main.userList = list(self.main.userSet)
        self.main.numUsers = len(self.main.userList)
        
        userRoleMatrix = self.main.user_role_mat
        if userNode.name in userRoleMatrix.keys():
            value = userRoleMatrix[userNode.name]
            if roleNode.name in value:
                value.remove(roleNode.name)
                if value == set():
                    del userRoleMatrix[userNode.name]
        del userNode
        
    def deleteDirNode(self, dirNode):
        if dirNode.dir == '/':
            QMessageBox.critical(self.main, 'Warning', 'Root directory must exist!')
            return
        self.sceneRight.removeItem(dirNode)
        self.main.dirNodes.remove(dirNode)
        self.main.dirSet.remove(dirNode.dir)
        self.main.dirList.remove(dirNode.dir)
        self.main.numDirs -= 1
        for level in self.main.role_res_mat.values():
            if dirNode.dir in level.keys():
                del level[dirNode.dir]
        self.recomputeDirHierForNodeRemoval(dirNode)
        self.recomputeEdgeForDirHier()
        del dirNode
            
    '''add item'''
    def addRoleToStorage(self, role):
        self.main.numRoles += 1
        self.main.roleSet.add(role)
        self.main.roleList.append(role)
        rolenode = self.createRoleNode(role)
        rolecompactnode = self.createRoleCompactNode(role)
        self.main.roleHier[len(self.main.roleHier)] = {0:[rolenode]}
        self.main.roleCompactHier[len(self.main.roleCompactHier)] = {0:[rolecompactnode]}
        self.main.role_adjmat[role] = rbacpolicy.makerolenode(set(), set())
        self.main.role_res_mat[role] = {}#{rbacpolicy.makepermset()}
        self.main.createMatrixView()
        self.main.updateMatrixView()
        self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
        if self.main.hasSolidEdgeFlag or self.main.role_adjmat != {}:
            self.main.evenlyLayout(self.scene, self.main.roleCompactHier)
        else:
            self.main.evenlyLayout(self.scene, self.main.roleCompactCompleteHier)
        self.main.viewModeChanged(self.main.currentAction)
    
    def addDirToStorage(self, direc):
        levels = direc.split('/')
        levels = filter(lambda a:a != '', levels)
        dirname = ''
        for i in xrange(len(levels)):
            dirname += '/'+levels[i]
            if dirname not in self.main.dirSet:
                self.main.numDirs += 1
                self.main.dirSet.add(dirname)
                self.main.dirList.append(dirname)
                dirnode = self.createDirNode(dirname)
                self.computeNewDirPosInHierarchy(dirnode)
        '''create edges'''
        self.recomputeEdgeForDirHier()
        self.main.updateMatrixView()
        self.main.evenlyLayoutNestedList(self.sceneRight, self.main.dirNodesHierarchy)
        self.main.viewModeChanged(self.main.currentAction)
    
    def addUserToStorage(self, user):
        self.main.numUsers += 1
        self.main.userSet.add(user)
        self.main.userList.append(user)
        self.main.user_role_mat[user] = set()
        self.createUserNode(user)
        self.main.updateMatrixView()
        self.main.viewModeChanged(self.main.currentAction)

    def addRoleToPolicy(self, roleName):
        if self.checkElementExistInList(roleName, self.main.roleList):
            QMessageBox.critical(self.main, 'Error', 'The role already exists!')
            self.main.toolBox.ui.addItemNameInputLineEdit.clear()
        else:
            self.addRoleToStorage(roleName)
            message = "Toolbox: Role("+roleName+"): Create\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
    
    
    def addDirToPolicy(self, dirName):
        if dirName[0] != '/':
            QMessageBox.critical(self.main, 'Error', "Please have the path of an object start with '/'.")
            return
        dirName = dirName.replace(' ', '')
        if self.checkElementExistInList(dirName, self.main.dirList) or dirName == '/':
            QMessageBox.critical(self.main, 'Error', 'The object already exists!')
            self.main.toolBox.ui.addItemNameInputLineEdit.clear()
        else:
            self.addDirToStorage(dirName)
            message = "Toolbox: Object("+dirName+"): Create\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
    
        
    def addUserToPolicy(self, userName):
        if self.checkElementExistInList(userName, self.main.userList):
            QMessageBox.critical(self.main, 'Error', 'The user already exists!')
            self.main.toolBox.ui.addItemNameInputLineEdit.clear()
        else:
            self.addUserToStorage(userName)
            message = "Toolbox: User("+userName+"): Create\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
    
    
    '''delete item'''
    def deleteRoleInStorage(self, roleName):
        self.main.numRoles -= 1
        self.main.roleSet.remove(roleName)
        self.main.roleList.remove(roleName)
        '''remove from scenes'''
#         for r in self.main.roleNodes:
#             if r.name == roleName:
#                 self.main.roleNodes.remove(r)
#                 self.scene.removeItem(r)
#                 rolenode = r
        for r in self.main.roleCompactNodes:
            if r.name == roleName:
                self.main.roleCompactNodes.remove(r)
                self.scene.removeItem(r)
                rolecompactnode = r
        for u in rolecompactnode.userNodes:
            self.deleteUserNodeForRoleNode(u, rolecompactnode)
        for e in self.scene.items():
            self.deleteEdgeItem(e, None, rolecompactnode)
        '''remove from hierarchy dict'''
        #MyFunctions.removeDictElementInValue(rolenode, self.main.roleHier)
        MyFunctions.removeDictElementInValue(rolecompactnode, self.main.roleCompactHier)
        #del rolenode
        del rolecompactnode
        '''remove from other dicts'''
        del self.main.role_adjmat[roleName]
        for level in self.main.role_adjmat.values():
            if roleName in level.parents:
                level.parents.remove(roleName)
            if roleName in level.children:
                level.children.remove(roleName)
        for level in self.main.user_role_mat.values():
            if roleName in level:
                level.remove(roleName)
        if roleName in self.main.role_res_mat.keys():
            del self.main.role_res_mat[roleName]
        self.main.updateMatrixView()
        self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
        if self.main.hasSolidEdgeFlag or self.main.role_adjmat == {}:
            self.main.evenlyLayout(self.scene, self.main.roleCompactHier)
        if len(self.main.roleCompactHier) == len(self.main.roleSet):
            self.main.evenlyLayout(self.scene, self.main.roleCompactCompleteHier)
        self.main.evenlyLayoutNestedList(self.sceneRight, self.main.dirNodesHierarchy)
        self.main.viewModeChanged(self.main.currentAction)
    
    def deleteRoleInPolicy(self, roleName):
        if not self.checkElementExistInList(roleName, self.main.roleList):
            QMessageBox.critical(self.main, 'Error', 'The role does not exist in this policy!')
        else:
            self.deleteRoleInStorage(roleName)
            message = "Toolbox: Role("+roleName+"): Delete\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
    
    
    def deleteDirInPolicy(self, dirName):
        for d in self.main.dirNodes:
            if d.dir == dirName:
                dirnode = d
        self.deleteDirNode(dirnode)
        self.main.updateMatrixView()
        self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
        if self.main.hasSolidEdgeFlag or self.main.role_adjmat == {}:
            self.main.evenlyLayout(self.scene, self.main.roleCompactHier)
        if len(self.main.roleCompactHier) == len(self.main.roleSet):
            self.main.evenlyLayout(self.scene, self.main.roleCompactCompleteHier)
        self.main.evenlyLayoutNestedList(self.sceneRight, self.main.dirNodesHierarchy)
        self.main.viewModeChanged(self.main.currentAction)
        message = "Toolbox: Object("+dirName+"): Delete\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        
    def deleteUserInPolicy(self, userName):
        usernodes = set()
        #for u in self.main.userNodes:
        for u in self.scene.items():
            if isinstance(u, UserNode) and u.name == userName:
                self.scene.removeItem(u)
                if u in self.main.userNodes:
                    self.main.userNodes.remove(u)
                if u.roleNode:
                    u.roleNode.userNodes.remove(u)
                usernodes.add(u)
        for e in self.scene.items():
            if isinstance(e, EdgeItem):
                if e.endItem in usernodes:
                    self.scene.removeItem(e)
                    del e
        for u in usernodes:
            del u
        self.main.userSet.remove(userName)
        self.main.userList.remove(userName)
        self.main.numUsers -= 1
        userRoleMatrix = self.main.user_role_mat
        if userName in userRoleMatrix.keys():
            del userRoleMatrix[userName]
        self.main.updateMatrixView()
        self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
        if self.main.hasSolidEdgeFlag or self.main.role_adjmat == {}:
            self.main.evenlyLayout(self.scene, self.main.roleCompactHier)
        if len(self.main.roleCompactHier) == len(self.main.roleSet):
            self.main.evenlyLayout(self.scene, self.main.roleCompactCompleteHier)
        self.main.viewModeChanged(self.main.currentAction)
        message = "Toolbox: User("+userName+"): Delete\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)

    
    def addRole_modifyDirInPolicy(self, item2Change, itemName1, recursive, permset):
        if itemName1 not in self.main.role_res_mat.keys():
            self.main.role_res_mat[itemName1] = {item2Change:rbacpolicy.makepermset(permset, recursive)}
        else:
            self.main.role_res_mat[itemName1][item2Change] = rbacpolicy.makepermset(permset, recursive)
        for r in self.main.roleCompactNodes:
            if r.name == itemName1:
                rolenode = r
        for d in self.main.dirNodes:
            if d.dir == item2Change:
                dirnode = d
        rolenode.dirNodes.append(dirnode)
        dirnode.roleNodes.append(rolenode)
        self.main.updateMatrixView()
        if self.main.clickedNode == rolenode:
            self.main.updateAllDirNodesForRoleClicked()
            self.main.clickedRelatedNodes.append(dirnode)
        elif self.main.clickedNode == dirnode:
            self.main.clickedRelatedNodes.append(rolenode)
            self.main.clickedRelatedNodes.extend(rolenode.userNodes)
            dirnode.highlightRoleNodes()
            self.main.updateAllUserNodes()        
        self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
        if self.main.hasSolidEdgeFlag or self.main.role_adjmat == {}:
            self.main.evenlyLayout(self.scene, self.main.roleCompactHier)
        if len(self.main.roleCompactHier) == len(self.main.roleSet):
            self.main.evenlyLayout(self.scene, self.main.roleCompactCompleteHier)
        self.main.viewModeChanged(self.main.currentAction)
        if recursive:
            r = '-r'
        else:
            r=''
        message = "Toolbox: Object("+item2Change+"): Add: Role("+itemName1+"): Perms("+r+'|'+','.join(permset)+")\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)

        
    def isUserInRole(self, usernode, rolenode):
        role = None
        for r in rolenode.allChildrenNodes:
            if usernode in r.userNodes:
                role = r.name
        if role != None:
            QMessageBox.warning(self.main, "This assignment is already implied by the inheritance between role '"+ \
                               rolenode.name+" and ' role '"+role+"'.")
            return True
        return False
    
    def addRole_modifyUserInPolicy(self, item2Change, itemName1):
            for r in self.main.roleCompactNodes:
                if r.name == itemName1:
                    rolenode = r
            for u in self.main.userNodes:
                    if u.name == item2Change:
                        usernode = u
            if not self.isUserInRole(usernode, rolenode):
                self.main.user_role_mat[item2Change].add(itemName1)
                '''add user node to the role node'''
                if usernode.roleNode:
                    usernode = self.createUserNode(item2Change)
                usernode.roleNode = rolenode
                rolenode.userNodes.append(usernode)
                edge = EdgeItem(EdgeItem.SEPARATE_ROLEUSER_CONN, rolenode, usernode, self.main)
                usernode.edgeList.append(edge)
                self.scene.addItem(edge)
                self.main.updateUserNodesPosOfRoleNode(rolenode)
                self.main.updateMatrixView()
                self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
                if self.main.hasSolidEdgeFlag or self.main.role_adjmat == {}:
                    self.main.evenlyLayout(self.scene, self.main.roleCompactHier)
                if len(self.main.roleCompactHier) == len(self.main.roleSet):
                    self.main.evenlyLayout(self.scene, self.main.roleCompactCompleteHier)
                self.main.viewModeChanged(self.main.currentAction)
                if rolenode in self.main.clickedRelatedNodes or rolenode == self.main.clickedNode:
                    rolenode.toggleUserNodes()
                    self.main.setEdgeHighlightState(edge, True)
                    self.main.updateEdgePositions()
            message = "Toolbox: User("+item2Change+"): Add: Role("+itemName1+")\n"
            self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
    
    '''delete connection'''
    def deleteRoleFromDirNode(self, rolename, dirname):
        del self.main.role_res_mat[rolename][dirname]
        if self.main.role_res_mat[rolename].keys() == []:
            del self.main.role_res_mat[rolename]
        for r in self.main.roleCompactNodes:
            if r.name == rolename:
                rolenode = r
        for d in self.main.dirNodes:
            if d.dir == dirname:
                dirnode = d     
        rolenode.dirNodes.remove(dirnode)
        dirnode.roleNodes.remove(rolenode) 
        if dirnode.roleNodes == []:
            self.deleteDirNode(dirnode)
        if self.main.clickedNode == rolenode:
            self.main.updateAllDirNodesForRoleClicked()
            self.main.clickedRelatedNodes.remove(dirnode)
        elif self.main.clickedNode == dirnode:
            self.main.clickedRelatedNodes.remove(rolenode)
            for u in rolenode.userNodes:
                self.main.clickedRelatedNodes.remove(u)
            dirnode.highlightRoleNodes()
            self.main.updateAllUserNodes()  
        self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
        if self.main.hasSolidEdgeFlag or self.main.role_adjmat == {}:
            self.main.evenlyLayout(self.scene, self.main.roleCompactHier)
        if len(self.main.roleCompactHier) == len(self.main.roleSet):
            self.main.evenlyLayout(self.scene, self.main.roleCompactCompleteHier)
        self.main.evenlyLayoutNestedList(self.sceneRight, self.main.dirNodesHierarchy)
        
    def deleteRole_modifyDirInPolicy(self, item2Change, itemName1, recursive, permset):
        perm = self.main.role_res_mat[itemName1][item2Change]
        if (recursive == False and permset == set())\
            or (recursive == perm.recursive and permset == perm.perms):
            self.deleteRoleFromDirNode(itemName1, item2Change)
        else:
            self.main.role_res_mat[itemName1][item2Change] = rbacpolicy.makepermset(permset, recursive)
        self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
        if self.main.hasSolidEdgeFlag or self.main.role_adjmat == {}:
            self.main.evenlyLayout(self.scene, self.main.roleCompactHier)
        if len(self.main.roleCompactHier) == len(self.main.roleSet):
            self.main.evenlyLayout(self.scene, self.main.roleCompactCompleteHier)
        self.main.updateMatrixView()
        self.main.viewModeChanged(self.main.currentAction)
        if recursive:
            r = '-r'
        else:
            r=''
        message = "Toolbox: Object("+item2Change+"): Delete: Role("+itemName1+"): Perms("+r+'|'+','.join(permset)+")\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)

        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
    
    def deleteRole_modifyUserInPolicy(self, item2Change, itemName1):
        self.main.user_role_mat[item2Change].remove(itemName1)
#         if self.main.user_role_mat[item2Change] == set():
#             del self.main.user_role_mat[item2Change]
#             self.main.userList.remove(item2Change)
#             self.main.userSet.remove(item2Change)
#             self.main.numUsers-=1
        for r in self.main.roleCompactNodes:
            if r.name == itemName1:
                rolenode = r
        for u in self.scene.items():
            if isinstance(u, UserNode) and u.name == item2Change and u.roleNode == rolenode:
                usernode = u
        rolenode.userNodes.remove(usernode)
        for e in usernode.edgeList:
            if e.startItem == rolenode:
                usernode.edgeList.remove(e)
                self.scene.removeItem(e)
        if self.main.user_role_mat[usernode.name]!=set():
            self.main.userNodes.remove(usernode)
            self.scene.removeItem(usernode)
            del usernode
        else:
            self.randomlyPlaceUsernode(usernode)
            usernode.roleNode = None
        self.main.updateUserNodesPosOfRoleNode(rolenode)
        self.main.updateMatrixView()
        self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
        if self.main.hasSolidEdgeFlag or self.main.role_adjmat == {}:
            self.main.evenlyLayout(self.scene, self.main.roleCompactHier)
        if len(self.main.roleCompactHier) == len(self.main.roleSet):
            self.main.evenlyLayout(self.scene, self.main.roleCompactCompleteHier)
        self.main.viewModeChanged(self.main.currentAction)
        if rolenode in self.main.clickedRelatedNodes or rolenode == self.main.clickedNode:
            rolenode.toggleUserNodes()
            self.main.updateEdgePositions()
        message = "Toolbox: User("+item2Change+"): Delete: Role("+itemName1+")\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
            
    def randomlyPlaceUsernode(self, usernode):
            x, y = MyFunctions.generateRandomCoordinates(0.4*self.scene.sceneRect().width(), 0.1*self.scene.sceneRect().height())
            usernode.setPos(x, y)
            usernode.relativeX = x/self.scene.sceneRect().width()
            usernode.relativeY = y/self.scene.sceneRect().height()
            
    '''role hierarchy modif'''
    def removeEdge(self, startnode, endnode):
        for e in self.scene.items():
            if isinstance(e, EdgeItem):
                if e.startItem == startnode and e.endItem == endnode:
                    self.scene.removeItem(e)
                    del e
                
    def areRelatedRoles(self, parentnode, childnode):
        if parentnode in childnode.allParentNodes:
            return True
            
    def addParent_modifyRoleInPolicy(self, item2Change, itemParent):  
        for r in self.main.roleCompactNodes:
            if item2Change == r.name:
                rolenode = r
            if itemParent == r.name:
                rolenodeparent = r
        
#         rolenode.parentNodes.add(rolenodeparent)
#         rolenodeparent.childrenNodes.add(rolenode)
#         indexGraph = 0
#         indexLevel = 0
#         for key, value in self.main.roleHier.iteritems():
#             for k, v in value.iteritems():
#                 if rolenode in v:
#                     indexGraph = key
#                     indexLevel = k
#         self.main.roleHier[indexGraph][indexLevel]
        for r in self.main.roleCompactNodes:
            if item2Change == r.name:
                rolecompactnode = r
            if itemParent == r.name:
                rolecompactnodeparent = r  
        if self.areRelatedRoles(rolecompactnodeparent, rolecompactnode):
            QMessageBox.warning(self.main, 'Warning', "This intended connection is already implied by the path from role '"\
                        +itemParent+"' to role '"+item2Change+"'.")
        else:
            self.createEdgeForRoleHier(rolenodeparent, rolenode)
            self.createEdgeForRoleCompactHier(rolecompactnodeparent, rolecompactnode)
            self.addParentInRoleAdjmat(item2Change, itemParent)
            self.addChildInRoleAdjmat(itemParent, item2Change)
            self.main.hasSolidEdgeFlag = True
        self.main.roleCompactHier = {}
        self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
        
        if self.main.hasSolidEdgeFlag or self.main.role_adjmat == {}:
            self.main.evenlyLayout(self.scene, self.main.roleCompactHier)
        if len(self.main.roleCompactHier) == len(self.main.roleSet):
            self.main.evenlyLayout(self.scene, self.main.roleCompactCompleteHier)
        self.main.evenlyLayoutNestedList(self.sceneRight, self.main.dirNodesHierarchy)
        self.main.viewModeChanged(self.main.currentAction)
    
    def deleteParent_modifyRoleInPolicy(self, item2Change, itemParent):  
        for r in self.main.roleCompactNodes:
            if item2Change == r.name:
                rolenode1 = r
            if itemParent == r.name:
                rolenodeparent1 = r
        self.deleteParentInRoleAdjmat(item2Change, itemParent)
        self.deleteChildInRoleAdjmat(itemParent, item2Change)
        rolenode1.parentNodes.remove(rolenodeparent1)
        rolenodeparent1.childrenNodes.remove(rolenode1)
        self.main.hasSolidEdgeFlag = False
        for e in self.scene.items():
            if isinstance(e, EdgeItem):
                self.main.hasSolidEdgeFlag = True
            self.deleteEdgeItem(e, rolenode1, rolenodeparent1, 1)
        self.main.roleCompactHier = {}
        self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
                    
        if self.main.hasSolidEdgeFlag or self.main.role_adjmat == {}:
            self.main.evenlyLayout(self.scene, self.main.roleCompactHier)
        if len(self.main.roleCompactHier) == len(self.main.roleSet):
            self.main.evenlyLayout(self.scene, self.main.roleCompactCompleteHier)
        self.main.evenlyLayoutNestedList(self.sceneRight, self.main.dirNodesHierarchy)
        self.main.viewModeChanged(self.main.currentAction)
    
    def addChild_modifyRoleInPolicy(self, item2Change, itemChild):  
        for r in self.main.roleCompactNodes:
            if item2Change == r.name:
                roleCompactnode = r
            if itemChild == r.name:
                roleCompactnodechild = r  
        if self.areRelatedRoles(roleCompactnode, roleCompactnodechild):
            QMessageBox.warning(self.main, 'Warning', "This intended connection is already implied by the path from role '"\
                        +item2Change+"' to role '"+itemChild+"'.")
        else:
            self.createEdgeForRoleCompactHier(roleCompactnode, roleCompactnodechild)
            self.addChildInRoleAdjmat(item2Change, itemChild)
            self.addParentInRoleAdjmat(itemChild, item2Change)
            self.main.hasSolidEdgeFlag = True
        self.main.roleCompactHier = {}
        self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
        if self.main.hasSolidEdgeFlag or self.main.role_adjmat == {}:
            self.main.evenlyLayout(self.scene, self.main.roleCompactHier)
        if len(self.main.roleCompactHier) == len(self.main.roleSet):
            self.main.evenlyLayout(self.scene, self.main.roleCompactCompleteHier)
        self.main.evenlyLayoutNestedList(self.sceneRight, self.main.dirNodesHierarchy)
        self.main.viewModeChanged(self.main.currentAction)
    
    def deleteChild_modifyRoleInPolicy(self, item2Change, itemChild):  
        for r in self.main.roleCompactNodes:
            if item2Change == r.name:
                rolenode1 = r
            if itemChild == r.name:
                rolenodechild1 = r
        self.deleteChildInRoleAdjmat(item2Change, itemChild)
        self.deleteParentInRoleAdjmat(itemChild, item2Change)
        rolenode1.childrenNodes.remove(rolenodechild1)
        rolenodechild1.parentNodes.remove(rolenode1)
        
        self.main.hasSolidEdgeFlag = False
        for e in self.scene.items():
            if isinstance(e, EdgeItem):
                self.main.hasSolidEdgeFlag = True
            self.deleteEdgeItem(e, rolenode1, rolenodechild1, 1)
       
        self.main.roleCompactHier = {}
        self.main.constructHierarchyForRoleNodes(self.main.roleCompactNodes, self.main.roleCompactHier)
        if self.main.hasSolidEdgeFlag or self.main.role_adjmat == {}:
            self.main.evenlyLayout(self.scene, self.main.roleCompactHier)
        if len(self.main.roleCompactHier) == len(self.main.roleSet):
            self.main.evenlyLayout(self.scene, self.main.roleCompactCompleteHier)
        self.main.evenlyLayoutNestedList(self.sceneRight, self.main.dirNodesHierarchy)
        self.main.viewModeChanged(self.main.currentAction)
    
    '''for view mode change'''
    def enableMainNormalMode(self):
        self.main.emptyClickedNodeInfo()
        self.mainMode = self.main.NORMAL_MODE
        for i in self.scene.items():
            i.highlighted = True
            if isinstance(i, RoleCompactNode):
                i.setUserNodesPosition(False)
        for i in self.sceneRight.items():
            i.highlighted = True
        self.main.updateAllScenes()
        self.main.toolBox.ui.rhierClickGroupBox.setEnabled(False)
            
    def enableMainHighlightMode(self):
        self.main.emptyClickedNodeInfo()
        self.mainMode = self.main.HIGHLIGHT_MODE
        self.disableAllNodes()
        self.main.toolBox.ui.rhierClickGroupBox.setEnabled(True)
    
    '''SEPARATE_VIEW'''
    '''for role hierarchy toggle in highlight mode'''
    def enableHighlightNoRHier(self):
        self.main.highlightmode = self.main.HIGHLIGHT_NO_HIER_MODE
        self.main.toolBox.ui.roleHighlightSchemeGroupBox.setEnabled(False)
        message = "Toolbox: Highlight: No inheritance\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        
    def enableHighlightWithRHier(self):
        self.main.highlightmode = self.main.HIGHLIGHT_HIER_MODE
        self.main.toolBox.ui.roleHighlightSchemeGroupBox.setEnabled(True)
        message = "Toolbox: Highlight: With inheritance\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        
    def setUnclickedNodesGrey(self):
        if self.main.highlightmode == self.main.HIGHLIGHT_HIER_MODE:
            for i in self.scene.items():
                if i not in self.main.clickedRelatedNodes and i != self.main.clickedNode:
                    i.highlighted = False
                    i.inheritHighlight = False
                else:
                    i.highlighted = True
            for i in self.sceneRight.items():
                if i not in self.main.clickedRelatedNodes and i != self.main.clickedNode:
                    i.highlighted = False
                    i.inheritHighlight = False
                else:
                    i.highlighted = True
                
    '''role nodes'''
    def highlightNodeWithBorderRoleNode(self, rolenode):
        self.main.clickedNode = rolenode
        self.main.clickedRelatedNodes = []
        rolenode.highlighted = True
        rolenode.inheritHighlight = False
        for d in rolenode.dirNodes:
            d.inheritHighlight = False
            MyFunctions.addItemToList(d, self.main.clickedRelatedNodes)
            d.highlighted = True
            if self.main.role_res_mat[rolenode.name][d.dir][1]:
                d.recursive = True
                for dd in d.allchildren:
                    dd.highlighted = True
                    dd.recursive = True
                    self.main.clickedRelatedNodes.append(dd)
            else:
                d.recursive = False
        for u in rolenode.userNodes:
            u.inheritHighlight = False
            MyFunctions.addItemToList(u, self.main.clickedRelatedNodes)
            u.highlighted = True
        if self.main.roleHighlightScheme == self.main.ROLE_HIGHLIGHT_BOTH:
            self.highlightChildrenNodesRoleNode(rolenode)
            self.highlightParentNodesRoleNode(rolenode)
        elif self.main.roleHighlightScheme == self.main.ROLE_HIGHLIGHT_CHILDREN:
            self.highlightChildrenNodesRoleNode(rolenode)
        elif self.main.roleHighlightScheme == self.main.ROLE_HIGHLIGHT_PARENTS:
            self.highlightParentNodesRoleNode(rolenode)
      
    def highlightParentNodesRoleNode(self, rolenode):
        if self.main.highlightmode == self.main.HIGHLIGHT_HIER_MODE:
            for r in rolenode.allParentNodes:
                r.inheritHighlight = True
                r.highlighted = True
                MyFunctions.addItemToList(r, self.main.clickedRelatedNodes)
                for d in r.dirNodes:
                    if d not in self.main.clickedRelatedNodes:
                        d.inheritHighlight = True
                        MyFunctions.addItemToList(d, self.main.clickedRelatedNodes)
                        d.highlighted = True
                for u in r.userNodes:
                    if u not in self.main.clickedRelatedNodes:
                        u.inheritHighlight = True
                        MyFunctions.addItemToList(u, self.main.clickedRelatedNodes)
                        u.highlighted = True
  
    def highlightChildrenNodesRoleNode(self, rolenode):
        if self.main.highlightmode == self.main.HIGHLIGHT_HIER_MODE:
            for r in rolenode.allChildrenNodes:
                r.inheritHighlight = True
                r.highlighted = True
                MyFunctions.addItemToList(r, self.main.clickedRelatedNodes)
                for d in r.dirNodes:
                    if d not in self.main.clickedRelatedNodes:
                        d.inheritHighlight = True
                        MyFunctions.addItemToList(d, self.main.clickedRelatedNodes)
                        d.highlighted = True
                for u in r.userNodes:
                    if u not in self.main.clickedRelatedNodes:
                        u.inheritHighlight = True
                        MyFunctions.addItemToList(u, self.main.clickedRelatedNodes)
                        u.highlighted = True

    '''dir nodes'''
    def highlightNodeWithBorderDirNode(self, dirnode):
        self.main.highlightmode = self.main.HIGHLIGHT_HIER_MODE
        self.main.clickedNode = dirnode
        self.main.clickedRelatedNodes = []
        dirnode.highlighted = True
        dirnode.inheritHighlight = False
        for r in dirnode.roleNodes:
            r.highlighted = True
            r.inheritHighlight = False
            MyFunctions.addItemToList(r, self.main.clickedRelatedNodes)
            if self.main.role_res_mat[r.name][dirnode.dir][1]:
                dirnode.recursive = True
#                 for dd in dirnode.allchildren:
#                     dd.highlighted = True
#                     dd.recursive = True
#                     self.main.clickedRelatedNodes.append(dd)
            for u in r.userNodes:
                u.highlighted = True
                u.inheritHighlight = False
                MyFunctions.addItemToList(u, self.main.clickedRelatedNodes)
        self.highlightParentNodesDirNode(dirnode)
           
    def highlightParentNodesDirNode(self, dirnode):
        for role in dirnode.roleNodes:
            for r in role.allParentNodes:
                if r not in self.main.clickedRelatedNodes:
                    r.inheritHighlight = True
                    r.highlighted = True
                    MyFunctions.addItemToList(r, self.main.clickedRelatedNodes)
                for u in r.userNodes:
                    if u not in self.main.clickedRelatedNodes:
                        u.inheritHighlight = True
                        MyFunctions.addItemToList(u, self.main.clickedRelatedNodes)
                        u.highlighted = True
                            
    '''user nodes'''
    def highlightNodeWithBorderUserNode(self, usernode):
        self.main.highlightmode = self.main.HIGHLIGHT_HIER_MODE
        self.main.clickedNode = usernode
        self.main.clickedRelatedNodes = []
        usernode.highlighted = True
        usernode.inheritHighlight = False
        directRolenodes = []
        childrenRolenodes = []
        for u in self.main.userNodes:
            u.highlighted = False
            u.inheritHighlight = False
            if u.name == usernode.name:
                if u!= usernode:
                    u.highlighted = True
                    u.inheritHighlight = False
                    self.main.clickedRelatedNodes.append(u)
                if u.roleNode:
                    directRolenodes.append(u.roleNode)
                    for r in u.roleNode.allChildrenNodes:
                        childrenRolenodes.append(r)
        for r in directRolenodes:        
            MyFunctions.addItemToList(r, self.main.clickedRelatedNodes)
            r.highlighted = True
            r.inheritHighlight = False
            for d in r.dirNodes:
                d.highlighted = True
                d.inheritHighlight = False
                MyFunctions.addItemToList(d, self.main.clickedRelatedNodes)
        self.highlightChildrenNodesUserNode(childrenRolenodes)
                        
    def highlightChildrenNodesUserNode(self, childrenRolenodes):
        for r in childrenRolenodes:
            if r not in self.main.clickedRelatedNodes:
                r.inheritHighlight = True
                r.highlighted = True
                MyFunctions.addItemToList(r, self.main.clickedRelatedNodes)
            for d in r.dirNodes:
                if d not in self.main.clickedRelatedNodes:
                    d.inheritHighlight = True
                    MyFunctions.addItemToList(d, self.main.clickedRelatedNodes)
                    d.highlighted = True
            for u in r.userNodes:
                if  u.name == self.main.clickedNode.name and u not in self.main.clickedRelatedNodes:
                    u.inheritHighlight = True
                    MyFunctions.addItemToList(u, self.main.clickedRelatedNodes)
                    u.highlighted = True
                        
    '''manipulate all nodes'''
    def highlightAllNodes(self):
        self.main.emptyClickedNodeInfo()
        self.main.mode = self.main.NORMAL_MODE
        if self.scene.displaySeparate:
            for r in self.main.roleCompactNodes:
                r.highlighted = True
                r.inheritHighlight = False
                r.toggleUserNodes()
            for u in self.main.userNodes:
                u.highlighted = True
                u.inheritHighlight = False
            for d in self.main.dirNodes:
                d.highlighted = True
                d.inheritHighlight = False
        self.main.updateAllScenes()
        self.main.specDialog.getSpecFromVisualization()
        message = "Toolbox: Highlight all role nodes\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
    
    def disableAllNodes(self):
        self.main.emptyClickedNodeInfo()
        self.main.mode = self.main.HIGHLIGHT_MODE
        if self.scene.displaySeparate:
            for r in self.main.roleCompactNodes:
                r.highlighted = False
                r.inheritHighlight = False
                r.toggleUserNodes()
            for u in self.main.userNodes:
                u.highlighted = False
                u.inheritHighlight = False
            for d in self.main.dirNodes:
                d.highlighted = False
                d.inheritHighlight = False
        self.main.updateAllScenes()
        self.main.specDialog.getSpecFromVisualization()
        message = "Toolbox: Highlight no role node\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
    
    def enableRoleChildScheme(self):
        self.main.roleHighlightScheme = self.main.ROLE_HIGHLIGHT_CHILDREN
        message = "Toolbox: Highlight: Inheritance: Children\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
        
    def enableRoleParentScheme(self):
        self.main.roleHighlightScheme = self.main.ROLE_HIGHLIGHT_PARENTS
        message = "Toolbox: Highlight: Inheritance: Parents\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
    
    def enableRoleBothScheme(self):
        self.main.roleHighlightScheme = self.main.ROLE_HIGHLIGHT_BOTH
        message = "Toolbox: Highlight: Inheritance: Parents and Children\n"
        self.main.writeToFile(self.main.logFile, self.main.getCurrentTimeString()+message)
    
    