net.firejack.platform.core.cache.CacheProcessor.java Source code

Java tutorial

Introduction

Here is the source code for net.firejack.platform.core.cache.CacheProcessor.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package net.firejack.platform.core.cache;

import net.firejack.platform.api.authority.domain.*;
import net.firejack.platform.api.config.domain.Config;
import net.firejack.platform.api.directory.domain.User;
import net.firejack.platform.api.registry.domain.Action;
import net.firejack.platform.api.registry.domain.Entity;
import net.firejack.platform.api.securitymanager.domain.SecuredRecordNode;
import net.firejack.platform.api.securitymanager.domain.SecuredRecordPermissions;
import net.firejack.platform.api.site.domain.NavigationElement;
import net.firejack.platform.core.domain.IdFilter;
import net.firejack.platform.core.model.registry.authority.*;
import net.firejack.platform.core.model.registry.config.ConfigModel;
import net.firejack.platform.core.model.registry.domain.ActionModel;
import net.firejack.platform.core.model.registry.domain.EntityModel;
import net.firejack.platform.core.model.registry.domain.PackageModel;
import net.firejack.platform.core.model.registry.site.NavigationElementModel;
import net.firejack.platform.core.store.registry.*;
import net.firejack.platform.core.store.user.IUserRoleStore;
import net.firejack.platform.core.store.user.IUserStore;
import net.firejack.platform.core.utils.CollectionUtils;
import net.firejack.platform.core.utils.ConfigContainer;
import net.firejack.platform.core.utils.Factory;
import net.firejack.platform.core.utils.StringUtils;
import net.firejack.platform.processor.cache.ConfigCacheProcessor;
import net.firejack.platform.web.cache.CacheManager;
import net.firejack.platform.web.cache.ICacheDataProcessor;
import net.firejack.platform.web.security.action.ActionComparator;
import net.firejack.platform.web.security.action.ActionDetectorFactory;
import net.firejack.platform.web.security.session.UserSessionManager;
import org.apache.commons.lang.ArrayUtils;
import org.apache.log4j.Logger;
import org.hibernate.criterion.Projections;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Scope("singleton")
@Component("cacheProcessor")
public class CacheProcessor implements ICacheDataProcessor {

    private static final Long EMPTY_SECURED_RECORD_ID = -1L;

    //    private final CachedSecurityDataContext cachedData = new CachedSecurityDataContext();

    private static final Logger logger = Logger.getLogger(CacheProcessor.class);

    @Autowired
    @Qualifier("permissionStore")
    private IPermissionStore permissionStore;

    @Autowired
    @Qualifier("roleStore")
    private IRoleStore roleStore;

    @Autowired
    @Qualifier("packageStore")
    private IPackageStore packageStore;

    @Autowired
    @Qualifier("actionStore")
    private IActionStore actionStore;

    @Autowired
    @Qualifier("resourceLocationStore")
    private IResourceLocationStore resourceLocationStore;

    @Autowired
    private INavigationElementStore navigationElementStore;

    @Autowired
    @Qualifier("userStore")
    private IUserStore userStore;

    @Autowired
    @Qualifier("userRoleStore")
    private IUserRoleStore userRoleStore;

    @Autowired
    @Qualifier("configStore")
    private IConfigStore configStore;

    @Autowired
    private ISecuredRecordStore securedRecordStore;

    @Autowired
    private IEntityStore entityStore;

    @Autowired
    private ConfigCacheProcessor configCacheProcessor;

    @Autowired
    private Factory modelFactory;

    private ScheduledExecutorService executor;

    /***/
    @PreDestroy
    public void destroy() {
        //       cachedData.clear();
        CacheManager.getInstance().close();
        if (executor != null) {
            executor.shutdown();
        }
    }

    public void loadData(boolean forceReload) {
        if (/*cachedData.isEmpty() || */forceReload) {
            //                cachedData.clear();
            List<RoleModel> roles = roleStore.findAll();
            if (roles != null) {
                Map<String, PackageModel> pkgByLookup = retrievePackageByLookup();
                List<String> packageLookupList = new LinkedList<String>(pkgByLookup.keySet());

                Map<String, List<NavigationElement>> navigationElementsByPackage = retrieveNavigationElementsByPackage(
                        packageLookupList);
                Map<String, SortedSet<Action>> actionsByPackage = retrieveActionsByPackage();
                Map<String, List<ResourceLocation>> resourceLocationsByPackage = retrieveResourceLocationsByPackage(
                        packageLookupList);
                Map<Long, SecuredRecordNode> securedRecords = retrieveSecuredRecords();
                Map<Long, List<UserPermission>> permissionsByRoles = retrieveGlobalPermissions(roles);
                Map<Long, SecuredRecordPermissions> securedRecordPermissions = retrieveSecuredRecordPermissions();

                Map<Long, List<Long>> userRoles = userStore.findAllRolesByUsers();
                Map<Long, Map<String, IdFilter>> readActionFiltersByUsers = populateReadActionFiltersInfo(
                        securedRecordPermissions, permissionsByRoles, userRoles);
                Map<String, List<Entity>> entitiesMap = retrieveEntityUpHierarchies();
                Map<String, Map<Long, UserContextPermissions>> userPermissionsByPackage = retrievePackageLevelUserPermissions();
                List<ConfigModel> configModels = configStore.findAll();

                CacheManager cacheManager = CacheManager.getInstance();
                for (Map.Entry<String, SortedSet<Action>> packageActions : actionsByPackage.entrySet()) {
                    List<Action> actionList = new LinkedList<Action>(packageActions.getValue());
                    cacheManager.setActions(packageActions.getKey(), actionList);
                }
                for (Map.Entry<String, List<NavigationElement>> navigationElementsEntry : navigationElementsByPackage
                        .entrySet()) {
                    cacheManager.setNavigationList(navigationElementsEntry.getKey(),
                            navigationElementsEntry.getValue());
                }
                for (Map.Entry<String, List<ResourceLocation>> packageResourceLocations : resourceLocationsByPackage
                        .entrySet()) {
                    cacheManager.setResourceLocations(packageResourceLocations.getKey(),
                            packageResourceLocations.getValue());
                }
                //
                for (Map.Entry<Long, List<UserPermission>> permissionsByRole : permissionsByRoles.entrySet()) {
                    cacheManager.setRolePermissions(permissionsByRole.getKey(), permissionsByRole.getValue());
                }
                for (Map.Entry<Long, SecuredRecordPermissions> securedRecordPermission : securedRecordPermissions
                        .entrySet()) {
                    cacheManager.setSecuredRecordPermissions(securedRecordPermission.getKey(),
                            securedRecordPermission.getValue());
                }
                for (Map.Entry<Long, Map<String, IdFilter>> readActionFiltersByUser : readActionFiltersByUsers
                        .entrySet()) {
                    cacheManager.setIdFiltersForUser(readActionFiltersByUser.getKey(),
                            readActionFiltersByUser.getValue());
                }
                for (Map.Entry<String, List<Entity>> entry : entitiesMap.entrySet()) {
                    cacheManager.setTypeWithSubclasses(entry.getKey(), entry.getValue());
                    Boolean securityEnabled = entry.getValue().get(0).getSecurityEnabled();
                    cacheManager.setEntityAsSecurityEnabled(entry.getKey(),
                            securityEnabled != null && securityEnabled);
                }
                for (Map.Entry<String, Map<Long, UserContextPermissions>> entry : userPermissionsByPackage
                        .entrySet()) {
                    Map<Long, UserContextPermissions> userPermissions = entry.getValue();
                    if (userPermissions != null) {
                        for (Map.Entry<Long, UserContextPermissions> userPermissionsEntry : userPermissions
                                .entrySet()) {
                            cacheManager.setPackageLevelUserPermissions(entry.getKey(),
                                    userPermissionsEntry.getKey(), userPermissionsEntry.getValue());
                        }
                    }
                }
                List<Config> configs = modelFactory.convertTo(Config.class, configModels);
                cacheManager.setConfigs(configs);

                cacheManager.setEntityTypes(new ArrayList<String>(entitiesMap.keySet()));
                cacheManager.setSecuredRecords(securedRecords);
                cacheManager.setUserRoles(userRoles);
                cacheManager.initializeGuestData(this);

                configCacheProcessor.initConfigs();
            }
        }
    }

    public void scheduleReload(int initialDelay, int delay, TimeUnit timeUnit) {
        executor = Executors.newSingleThreadScheduledExecutor();
        executor.scheduleWithFixedDelay(new Runnable() {
            @Override
            public void run() {
                loadData(true);
            }
        }, initialDelay, delay, timeUnit);
    }

    @Override
    public void addNewPackage(String lookup) {
        if (StringUtils.isNotBlank(lookup)) {
            CacheManager cacheManager = CacheManager.getInstance();
            List<NavigationElement> navigationElements = cacheManager.getNavigationList(lookup);
            if (navigationElements == null) {
                cacheManager.setNavigationList(lookup, new LinkedList<NavigationElement>());
            }

            List<Action> actions = cacheManager.getActions(lookup);
            if (actions == null) {
                cacheManager.setActions(lookup, new LinkedList<Action>());
            }

            List<ResourceLocation> resourceLocations = cacheManager.getResourceLocations(lookup);
            if (resourceLocations == null) {
                cacheManager.setResourceLocations(lookup, new ArrayList<ResourceLocation>());
            }
        }
    }

    @Override
    public void updatePackage(String oldLookup, String newLookup) {
        if (ConfigContainer.isAppInstalled() && StringUtils.isNotBlank(oldLookup)
                && StringUtils.isNotBlank(newLookup) && !oldLookup.equals(newLookup)) {
            CacheManager cacheManager = CacheManager.getInstance();

            List<NavigationElement> oldNavigationElements = cacheManager.getNavigationList(oldLookup);
            List<NavigationElement> newNavigationElements = cacheManager.getNavigationList(newLookup);
            if (oldNavigationElements != null && newNavigationElements == null) {
                cacheManager.removeNavigationList(oldLookup);
                cacheManager.setNavigationList(newLookup, oldNavigationElements);
            }

            List<Action> oldActions = cacheManager.getActions(oldLookup);
            List<Action> newActions = cacheManager.getActions(newLookup);
            if (oldActions != null && newActions == null) {
                cacheManager.removeActions(oldLookup);
                cacheManager.setActions(newLookup, oldActions);
            }

            List<ResourceLocation> oldResourceLocations = cacheManager.getResourceLocations(oldLookup);
            List<ResourceLocation> newResourceLocations = cacheManager.getResourceLocations(newLookup);
            if (oldResourceLocations != null && newResourceLocations == null) {
                cacheManager.removeResourceLocations(oldLookup);
                cacheManager.setResourceLocations(newLookup, oldResourceLocations);
            }
        }
    }

    @Override
    public void removePackage(String lookup) {
        if (ConfigContainer.isAppInstalled() && StringUtils.isNotBlank(lookup)) {
            CacheManager cacheManager = CacheManager.getInstance();
            cacheManager.removeNavigationList(lookup);
            cacheManager.removeActions(lookup);
            cacheManager.removeResourceLocations(lookup);
        }
    }

    @Override
    public List<Long> getUserRoles(Long userId) {
        List<Long> result = new ArrayList<Long>();
        if (userId != null) {
            CacheManager cacheManager = CacheManager.getInstance();
            Map<Long, List<Long>> userRoles = cacheManager.getUserRoles();
            List<Long> roleList;
            if (userRoles != null && ((roleList = userRoles.get(userId)) != null)) {
                result = roleList;
            }
        }
        return result;
    }

    @Override
    public void updateRolePermissions(Long roleId, List<String> permissions, boolean isGuest) {
        if (!ConfigContainer.isAppInstalled()) {
            return;
        }
        if (roleId == null) {
            throw new IllegalArgumentException("Role id should not be null.");
        }
        permissions = permissions == null ? new ArrayList<String>() : permissions;

        CacheManager cacheManager = CacheManager.getInstance();
        List<UserPermission> rolePermissions = cacheManager.getRolePermissions(roleId);

        if (rolePermissions != null) {
            List<UserPermission> newRolePermissions = AuthorizationVOFactory.convertPermissionsEx(permissions);
            cacheManager.setRolePermissions(roleId, newRolePermissions);

            //update id filters
            Map<Long, List<Long>> userRoles = cacheManager.getUserRoles();
            for (Map.Entry<Long, List<Long>> entry : userRoles.entrySet()) {
                if (entry.getValue().contains(roleId)) {
                    updateIdFiltersOnRolesChange(entry.getKey(), entry.getValue());
                }
            }
            //finish update id filters

            UserSessionManager.getInstance().updateRolePermissionsForOpenedSessions(roleId, newRolePermissions);
        } else {
            Map<Long, SecuredRecordPermissions> srPermissionsMap = cacheManager.getAllSecuredRecordPermissions();
            Set<Long> userIdSet = null;
            for (SecuredRecordPermissions srPermissions : srPermissionsMap.values()) {
                for (UserContextPermissions userContextPermissions : srPermissions.getUserContextPermissions()
                        .values()) {
                    ContextPermissions contextPermissions = userContextPermissions.getContextPermissions(roleId);
                    if (contextPermissions != null) {
                        contextPermissions.setPermissions(permissions);
                        cacheManager.setSecuredRecordPermissions(srPermissions.getSecuredRecordId(), srPermissions);//!
                        if (userIdSet == null) {
                            userIdSet = new HashSet<Long>();
                        }
                        userIdSet.add(userContextPermissions.getUserId());
                    }
                }
            }
            if (userIdSet != null) {
                for (Long userId : userIdSet) {
                    Map<Long, Map<Long, List<UserPermission>>> userPermissionsBySecuredRecords = getUserPermissionsBySecuredRecords(
                            userId);
                    UserSessionManager.getInstance().refreshUserContextRolePermissions(userId,
                            userPermissionsBySecuredRecords);
                }
            }
            //if roleId was not found in neither in usual roles cache nor in context role cache, then it's a new role and this role with permissions will be added with addUserContextPermissions(  when necessary

            //todo: temp solution while we support package level permissions
            Map<Long, List<Long>> userRoles = cacheManager.getUserRoles();
            List<String> packageLookupList = packageStore.searchWithProjection(null, Projections.property("lookup"),
                    null);

            List<UserPermission> newRolePermissions = null;
            for (Long userId : userRoles.keySet()) {
                for (String packageLookup : packageLookupList) {
                    UserContextPermissions packageLevelPermissions = cacheManager
                            .getPackageLevelUserPermissions(packageLookup, userId);
                    if (packageLevelPermissions != null
                            && packageLevelPermissions.getRolePermissions().containsKey(roleId)) {
                        if (newRolePermissions == null) {
                            newRolePermissions = AuthorizationVOFactory.convertPermissionsEx(permissions);
                        }
                        packageLevelPermissions.getRolePermissions().put(roleId, newRolePermissions);
                        cacheManager.setPackageLevelUserPermissions(packageLookup, userId, packageLevelPermissions);
                    }

                }
            }
        }
        if (isGuest && UserSessionManager.getGuestRoleIds().add(roleId)
                || !isGuest && UserSessionManager.getGuestRoleIds().remove(roleId)) {
            cacheManager.initializeGuestData(this);
        }
    }

    @Override
    public void addPackageRole(Long roleId, List<UserPermission> permissions, boolean isGuest) {
        if (ConfigContainer.isAppInstalled() && roleId != null) {
            CacheManager cacheManager = CacheManager.getInstance();
            List<UserPermission> rolePermissions = cacheManager.getRolePermissions(roleId);
            if (rolePermissions == null) {
                List<UserPermission> userPermissions = permissions == null ? new LinkedList<UserPermission>()
                        : permissions;
                cacheManager.setRolePermissions(roleId, userPermissions);
                UserSessionManager userSessionManager = UserSessionManager.getInstance();
                userSessionManager.refreshRolePermissions();
                if (isGuest) {
                    UserSessionManager.getGuestRoleIds().add(roleId);
                    cacheManager.initializeGuestData(this);
                }
            }
        }
    }

    @Override
    public void deleteRole(Long roleId) {
        if (ConfigContainer.isAppInstalled() && roleId != null) {
            CacheManager cacheManager = CacheManager.getInstance();
            cacheManager.removeRolePermissions(roleId);

            Map<Long, List<Long>> userRoles = cacheManager.getUserRoles();
            for (Map.Entry<Long, List<Long>> entry : userRoles.entrySet()) {
                if (entry.getValue().contains(roleId)) {
                    entry.getValue().remove(roleId);
                    updateIdFiltersOnRolesChange(entry.getKey(), entry.getValue());
                }
            }
            cacheManager.setUserRoles(userRoles);
            UserSessionManager.getInstance().deleteRole(roleId);
            boolean isGuest = UserSessionManager.getGuestRoleIds().remove(roleId);
            if (isGuest) {
                cacheManager.initializeGuestData(this);
            }
        }
    }

    @Override
    public void addNavigation(NavigationElement navigation) {
        if (navigation != null) {
            boolean navigationAdded = false;
            CacheManager cacheManager = CacheManager.getInstance();
            Map<String, List<NavigationElement>> navigationElements = cacheManager.getAllNavigationElements();
            if (navigationElements != null) {
                for (Map.Entry<String, List<NavigationElement>> packageNavigationVOs : navigationElements
                        .entrySet()) {
                    if (navigation.getLookup().startsWith(packageNavigationVOs.getKey() + ".")) {
                        packageNavigationVOs.getValue().add(navigation);
                        cacheManager.setNavigationList(packageNavigationVOs.getKey(),
                                packageNavigationVOs.getValue());
                        navigationAdded = true;
                        break;
                    }
                }
            }
            if (!navigationAdded) {
                logger.error(
                        "Failed to update Firejack Platform Node cache with new navigation. Reason: Failed to find suitable package mapping.");
            }
        }
    }

    @Override
    public void addNavigationElements(List<NavigationElement> navigations) {
        if (navigations != null && !navigations.isEmpty()) {
            CacheManager cacheManager = CacheManager.getInstance();
            Map<String, List<NavigationElement>> navigationElements = cacheManager.getAllNavigationElements();
            if (navigationElements != null) {
                for (Map.Entry<String, List<NavigationElement>> packageNavigationEntry : navigationElements
                        .entrySet()) {
                    int oldSize = packageNavigationEntry.getValue().size();
                    for (NavigationElement navigation : navigations) {
                        if (navigation.getLookup().startsWith(packageNavigationEntry.getKey())
                                && !packageNavigationEntry.getValue().contains(navigation)) {
                            packageNavigationEntry.getValue().add(navigation);
                        }
                    }
                    if (oldSize != packageNavigationEntry.getValue().size()) {
                        cacheManager.setNavigationList(packageNavigationEntry.getKey(),
                                packageNavigationEntry.getValue());
                    }
                }
            } else {
                logger.error(
                        "Failed to update Firejack Platform Node cache with new navigation elements. Reason: Trying to add navigation elements while no packages registered yet.");
            }
        }
    }

    @Override
    public void addResourceLocations(List<ResourceLocation> rlList) {
        if (rlList != null && !rlList.isEmpty()) {
            CacheManager cacheManager = CacheManager.getInstance();
            Map<String, List<ResourceLocation>> resourceLocations = cacheManager.getAllResourceLocations();
            if (resourceLocations != null) {
                for (Map.Entry<String, List<ResourceLocation>> packageRLEntry : resourceLocations.entrySet()) {
                    int oldSize = packageRLEntry.getValue().size();
                    for (ResourceLocation resourceLocation : rlList) {
                        if (resourceLocation.getLookup().startsWith(packageRLEntry.getKey())
                                && !packageRLEntry.getValue().contains(resourceLocation)) {
                            packageRLEntry.getValue().add(resourceLocation);
                        }
                    }
                    if (oldSize != packageRLEntry.getValue().size()) {
                        cacheManager.setResourceLocations(packageRLEntry.getKey(), packageRLEntry.getValue());
                    }
                }
            } else {
                logger.error(
                        "Failed to update Firejack Platform Node cache with new navigation elements. Reason: Trying to add navigation elements while no packages registered yet.");
            }
        }
    }

    @Override
    public void updateNavigation(NavigationElement navigation) {
        if (navigation != null) {
            boolean navigationAdded = false;
            CacheManager cacheManager = CacheManager.getInstance();
            Map<String, List<NavigationElement>> navigationElements = cacheManager.getAllNavigationElements();
            if (navigationElements != null) {
                for (Map.Entry<String, List<NavigationElement>> navigationListEntry : navigationElements
                        .entrySet()) {
                    for (NavigationElement nav : navigationListEntry.getValue()) {
                        if (nav.getId().equals(navigation.getId())) {
                            navigationListEntry.getValue().remove(nav);
                            navigationListEntry.getValue().add(navigation);
                            cacheManager.setNavigationList(navigationListEntry.getKey(),
                                    navigationListEntry.getValue());

                            if (nav.getPermissions() != null && navigation.getPermissions() != null) {
                                List<UserPermission> oldPermissionList = new LinkedList<UserPermission>();
                                for (Permission permission : nav.getPermissions()) {
                                    oldPermissionList.add(new UserPermission(permission.getLookup()));
                                }
                                List<UserPermission> newPermissionList = new LinkedList<UserPermission>();
                                for (Permission permission : navigation.getPermissions()) {
                                    newPermissionList.add(new UserPermission(permission.getLookup()));
                                }
                                updatePermissions(oldPermissionList, newPermissionList);
                            }

                            navigationAdded = true;
                            break;
                        }
                    }
                }
            }
            if (!navigationAdded) {
                logger.error("Failed to update Firejack Platform Node cache with updated navigation");
            }
        }
    }

    @Override
    public void removeNavigation(NavigationElement navigation) {
        if (ConfigContainer.isAppInstalled() && navigation != null) {
            boolean navigationRemoved = false;
            CacheManager cacheManager = CacheManager.getInstance();
            Map<String, List<NavigationElement>> navigationElements = cacheManager.getAllNavigationElements();
            if (navigationElements != null) {
                for (Map.Entry<String, List<NavigationElement>> navigationListEntry : navigationElements
                        .entrySet()) {
                    if (navigationListEntry.getValue().contains(navigation)) {
                        if (navigationListEntry.getValue().remove(navigation)) {
                            CacheManager.getInstance().setNavigationList(navigationListEntry.getKey(),
                                    navigationListEntry.getValue());
                            navigationRemoved = true;
                            break;
                        } else {
                            logger.error("Failed to remove element in container.");
                        }
                    }
                }
            }
            if (!navigationRemoved) {
                logger.error(
                        "Failed to update Firejack Platform Node cache. Navigation for removal was not found.");
            }
        }
    }

    @Override
    public Map<String, List<NavigationElement>> getNavigationElements() {
        CacheManager cacheManager = CacheManager.getInstance();
        return cacheManager.getAllNavigationElements();
    }

    @Override
    public Map<Long, List<UserPermission>> getPermissionsByRoles(Long... roles) {
        Map<Long, List<UserPermission>> permissions = new HashMap<Long, List<UserPermission>>();
        CacheManager cacheManager = CacheManager.getInstance();
        for (Long roleId : roles) {
            List<UserPermission> rolePermissions = cacheManager.getRolePermissions(roleId);
            permissions.put(roleId, rolePermissions);
        }
        return permissions;
    }

    @Override
    public void updatePermissions(List<UserPermission> permissionsToUpdate,
            List<UserPermission> updatedPermissions) {
        if (permissionsToUpdate != null && updatedPermissions != null
                && permissionsToUpdate.size() == updatedPermissions.size()) {
            CacheManager cacheManager = CacheManager.getInstance();
            Map<Long, List<UserPermission>> rolePermissions = cacheManager.getAllRolePermissions();
            if (rolePermissions != null) {
                for (int i = 0; i < permissionsToUpdate.size(); i++) {
                    for (Map.Entry<Long, List<UserPermission>> userPermissionEntry : rolePermissions.entrySet()) {
                        Long roleId = userPermissionEntry.getKey();
                        List<UserPermission> userPermissions = userPermissionEntry.getValue();
                        UserPermission permissionToUpdate = permissionsToUpdate.get(i);
                        if (userPermissions.contains(permissionToUpdate)) {
                            userPermissions.remove(permissionToUpdate);
                            UserPermission updatedPermission = updatedPermissions.get(i);
                            userPermissions.add(updatedPermission);
                            String oldEntityType;
                            if ((oldEntityType = getReadPermissionType(permissionToUpdate)) != null) {
                                Map<Long, Map<String, IdFilter>> readActionFiltersByUser = cacheManager
                                        .getAllIdFiltersForUser();
                                for (Map.Entry<Long, Map<String, IdFilter>> entry : readActionFiltersByUser
                                        .entrySet()) {
                                    if (entry.getValue().containsKey(oldEntityType)) {
                                        IdFilter idFilterInfo = entry.getValue().remove(oldEntityType);
                                        if (idFilterInfo != null) {
                                            String newEntityType = ActionDetectorFactory
                                                    .isReadPermission(updatedPermission)
                                                            ? ActionDetectorFactory
                                                                    .getReadPermissionType(updatedPermission)
                                                            : ActionDetectorFactory.getReadAllPermissionType(
                                                                    updatedPermission.getPermission());
                                            entry.getValue().put(newEntityType, idFilterInfo);
                                            cacheManager.setIdFiltersForUser(entry.getKey(), entry.getValue());
                                        }
                                    }
                                }
                            }
                            cacheManager.setRolePermissions(roleId, userPermissions);
                        }
                    }
                }
                UserSessionManager.getInstance().refreshRolePermissions();
            }
        }
    }

    @Override
    public void removePermissions(List<UserPermission> permissionsToDelete) {
        if (ConfigContainer.isAppInstalled() && permissionsToDelete != null) {
            CacheManager cacheManager = CacheManager.getInstance();
            Map<Long, List<UserPermission>> rolePermissions = cacheManager.getAllRolePermissions();
            if (rolePermissions != null) {
                List<Long> updatedRoles = new ArrayList<Long>();
                for (Map.Entry<Long, List<UserPermission>> entry : rolePermissions.entrySet()) {
                    List<UserPermission> permissions = entry.getValue();
                    if (permissions != null && permissions.removeAll(permissionsToDelete)) {
                        updatedRoles.add(entry.getKey());
                    }
                }
                //update id filters
                if (!updatedRoles.isEmpty()) {
                    for (Map.Entry<Long, List<Long>> entry : cacheManager.getUserRoles().entrySet()) {
                        if (CollectionUtils.containsAny(entry.getValue(), updatedRoles)) {
                            updateIdFiltersOnRolesChange(entry.getKey(), entry.getValue());
                        }
                    }
                }
                UserSessionManager.getInstance().refreshRolePermissions();
            }
        }
    }

    @Override
    public void removePermission(UserPermission permissionToDelete) {
        if (ConfigContainer.isAppInstalled() && permissionToDelete != null) {
            CacheManager cacheManager = CacheManager.getInstance();
            Map<Long, List<UserPermission>> rolePermissions = cacheManager.getAllRolePermissions();
            if (rolePermissions != null) {
                List<Long> updatedRoles = new ArrayList<Long>();
                for (Map.Entry<Long, List<UserPermission>> entry : rolePermissions.entrySet()) {
                    List<UserPermission> permissions = entry.getValue();
                    if (permissions != null && permissions.remove(permissionToDelete)) {
                        updatedRoles.add(entry.getKey());
                    }
                }
                //update id filters
                if (!updatedRoles.isEmpty()) {
                    for (Map.Entry<Long, List<Long>> entry : cacheManager.getUserRoles().entrySet()) {
                        if (CollectionUtils.containsAny(entry.getValue(), updatedRoles)) {
                            updateIdFiltersOnRolesChange(entry.getKey(), entry.getValue());
                        }
                    }
                }
                UserSessionManager.getInstance().refreshRolePermissions();
            }
        }
    }

    public void setUserRole(User userInfo, List<Long> roleIdList) {
        if (ConfigContainer.isAppInstalled() && userInfo != null && roleIdList != null) {
            CacheManager cacheManager = CacheManager.getInstance();
            Map<Long, List<UserPermission>> rolePermissions = cacheManager.getAllRolePermissions();
            if (rolePermissions != null) {
                UserSessionManager sessionManager = UserSessionManager.getInstance();
                Map<Long, List<Long>> userRoles = cacheManager.getUserRoles();
                userRoles.put(userInfo.getId(), roleIdList);
                cacheManager.setUserRoles(userRoles);

                //update id filters
                updateIdFiltersOnRolesChange(userInfo.getId(), roleIdList);

                sessionManager.refreshUserRoles(userInfo, roleIdList);
                sessionManager.refreshRolePermissions();
            }
        }
    }

    public void addUserRole(Long userId, Long roleId) {
        if (userId != null && roleId != null) {
            CacheManager cacheManager = CacheManager.getInstance();
            Map<Long, List<Long>> rolesByUser = cacheManager.getUserRoles();
            List<Long> userRoles = rolesByUser.get(userId);
            if (userRoles == null) {
                userRoles = new ArrayList<Long>();
                rolesByUser.put(userId, userRoles);
            }
            if (!userRoles.contains(roleId)) {
                userRoles.add(roleId);
                updateIdFiltersOnRolesChange(userId, rolesByUser.get(userId));
            }
            cacheManager.setUserRoles(rolesByUser);
            UserSessionManager.getInstance().addUserRole(userId, roleId, this);
        }
    }

    @Override
    public void deleteUserRole(Long userId, Long roleId) {
        if (userId != null && roleId != null) {
            UserSessionManager userSessionManager = UserSessionManager.getInstance();

            boolean deleted = false;
            CacheManager cacheManager = CacheManager.getInstance();
            //check whether role is contextual and if yes then update contextual roles cache data
            Map<Long, SecuredRecordPermissions> userContextRolePermissions = cacheManager
                    .getAllSecuredRecordPermissions();
            for (SecuredRecordPermissions securedRecordPermissions : userContextRolePermissions.values()) {
                UserContextPermissions userRolePermissions = securedRecordPermissions.getUserContextPermissions()
                        .get(userId);
                if (userRolePermissions != null) {
                    ContextPermissions removedContextPermissions = userRolePermissions.removeContextRole(roleId);
                    if (removedContextPermissions != null) {
                        Map<String, IdFilter> userIdFilters = cacheManager.getIdFiltersForUser(userId);
                        if (userIdFilters != null) {
                            boolean updated = false;
                            for (UserPermission permission : removedContextPermissions.userPermissionsSnapshot()) {
                                if (ActionDetectorFactory.isReadPermission(permission)) {
                                    String entityType = ActionDetectorFactory.getReadPermissionType(permission);
                                    IdFilter idFilter = userIdFilters.get(entityType);
                                    if (idFilter != null) {
                                        Long entityId = Long.valueOf(permission.getEntityId());
                                        if (ArrayUtils.contains(idFilter.getGrantedIdList(), entityId)) {
                                            List<Long> grantedIdList = new ArrayList<Long>(
                                                    Arrays.asList(idFilter.getGrantedIdList()));
                                            grantedIdList.remove(entityId);
                                            idFilter.setGrantedIdList(
                                                    grantedIdList.toArray(new Long[grantedIdList.size()]));
                                            updated = true;
                                        }
                                    }
                                }
                            }
                            if (updated) {
                                cacheManager.setIdFiltersForUser(userId, userIdFilters);
                            }
                        }

                        userSessionManager.refreshUserContextRolePermissions(userId,
                                getUserPermissionsBySecuredRecords(userId));
                        deleted = true;
                    }
                }
            }

            if (!deleted) {//if role was not found among contextual roles then remove usual role
                userSessionManager.removeUsualUserRole(userId, roleId, this);
                Map<Long, List<Long>> rolesByUser = cacheManager.getUserRoles();
                List<Long> userRoles = rolesByUser.get(userId);
                if (userRoles != null) {
                    userRoles.remove(roleId);
                    cacheManager.setUserRoles(rolesByUser);
                }
            }
        }
    }

    @Override
    public void deleteContextUserRoles(Map<Long, Collection<ContextPermissions>> userRoles) {
        if (userRoles != null && !userRoles.isEmpty()) {
            UserSessionManager userSessionManager = UserSessionManager.getInstance();

            CacheManager cacheManager = CacheManager.getInstance();
            //check whether role is contextual and if yes then update contextual roles cache data
            Map<Long, SecuredRecordPermissions> userContextRolePermissions = cacheManager
                    .getAllSecuredRecordPermissions();
            for (Map.Entry<Long, Collection<ContextPermissions>> userRoleEntry : userRoles.entrySet()) {
                Long userId = userRoleEntry.getKey();
                for (SecuredRecordPermissions securedRecordPermissions : userContextRolePermissions.values()) {
                    UserContextPermissions userRolePermissions = securedRecordPermissions
                            .getUserContextPermissions().get(userId);
                    if (userRolePermissions != null) {
                        Collection<ContextPermissions> roles = userRoleEntry.getValue();
                        if (roles != null) {
                            for (ContextPermissions role : roles) {
                                ContextPermissions removedContextPermissions = userRolePermissions
                                        .removeContextRole(role);
                                if (removedContextPermissions != null) {
                                    Map<String, IdFilter> userIdFilters = cacheManager.getIdFiltersForUser(userId);
                                    if (userIdFilters != null) {
                                        boolean updated = false;
                                        for (UserPermission permission : removedContextPermissions
                                                .userPermissionsSnapshot()) {
                                            if (ActionDetectorFactory.isReadPermission(permission)) {
                                                String entityType = ActionDetectorFactory
                                                        .getReadPermissionType(permission);
                                                IdFilter idFilter = userIdFilters.get(entityType);
                                                if (idFilter != null) {
                                                    Long entityId = Long.valueOf(permission.getEntityId());
                                                    if (ArrayUtils.contains(idFilter.getGrantedIdList(),
                                                            entityId)) {
                                                        List<Long> grantedIdList = new ArrayList<Long>(
                                                                Arrays.asList(idFilter.getGrantedIdList()));
                                                        grantedIdList.remove(entityId);
                                                        idFilter.setGrantedIdList(grantedIdList
                                                                .toArray(new Long[grantedIdList.size()]));
                                                        updated = true;
                                                    }
                                                }
                                            }
                                        }
                                        if (updated) {
                                            cacheManager.setIdFiltersForUser(userId, userIdFilters);
                                        }
                                    }
                                    userSessionManager.refreshUserContextRolePermissions(userId,
                                            getUserPermissionsBySecuredRecords(userId));
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    @Override
    public Map<String, List<ResourceLocation>> getResourceLocations() {
        CacheManager cacheManager = CacheManager.getInstance();
        return cacheManager.getAllResourceLocations();
    }

    @Override
    public void addResourceLocation(ResourceLocation resourceLocation) {
        if (ConfigContainer.isAppInstalled() && resourceLocation != null) {
            boolean resourceLocationAdded = false;
            CacheManager cacheManager = CacheManager.getInstance();
            Map<String, List<ResourceLocation>> resourceLocations = cacheManager.getAllResourceLocations();
            if (resourceLocations != null) {
                for (Map.Entry<String, List<ResourceLocation>> resourceLocationEntry : resourceLocations
                        .entrySet()) {
                    if (resourceLocation.getLookup().startsWith(resourceLocationEntry.getKey() + ".")) {
                        resourceLocationEntry.getValue().add(resourceLocation);
                        cacheManager.setResourceLocations(resourceLocationEntry.getKey(),
                                resourceLocationEntry.getValue());
                        resourceLocationAdded = true;
                        break;
                    }
                }
            }
            if (!resourceLocationAdded) {
                logger.error("Failed to update Firejack Platform Node cache. Resource Location was not updated.");
            }
        }
    }

    @Override
    public void updateResourceLocation(ResourceLocation resourceLocation) {
        if (ConfigContainer.isAppInstalled() && resourceLocation != null) {
            boolean resourceLocationUpdated = false;
            CacheManager cacheManager = CacheManager.getInstance();
            Map<String, List<ResourceLocation>> resourceLocations = cacheManager.getAllResourceLocations();
            if (resourceLocations != null) {
                for (Map.Entry<String, List<ResourceLocation>> entry : resourceLocations.entrySet()) {
                    for (ResourceLocation rl : entry.getValue()) {
                        if (rl.getId().equals(resourceLocation.getId())) {
                            if (entry.getValue().remove(rl)) {
                                entry.getValue().add(resourceLocation);
                                cacheManager.setResourceLocations(entry.getKey(), entry.getValue());
                                resourceLocationUpdated = true;
                                break;
                            } else {
                                logger.error(
                                        "Failed to update resource location element. Reason: old element was not removed.");
                            }
                        }
                    }
                }
            }
            if (!resourceLocationUpdated) {
                logger.error("Failed to update Firejack Platform Node cache. Resource Location was not updated.");
            }
        }
    }

    @Override
    public void removeResourceLocation(ResourceLocation resourceLocation) {
        if (ConfigContainer.isAppInstalled()) {
            boolean resourceLocationsRemoved = false;
            CacheManager cacheManager = CacheManager.getInstance();
            Map<String, List<ResourceLocation>> resourceLocations = cacheManager.getAllResourceLocations();
            if (resourceLocations != null) {
                for (Map.Entry<String, List<ResourceLocation>> resourceLocationEntry : resourceLocations
                        .entrySet()) {
                    if (resourceLocation.getLookup().startsWith(resourceLocationEntry.getKey() + ".")) {
                        if (resourceLocationEntry.getValue().remove(resourceLocation)) {
                            cacheManager.setResourceLocations(resourceLocationEntry.getKey(),
                                    resourceLocationEntry.getValue());
                            resourceLocationsRemoved = true;
                        } else {
                            logger.error("Failed to remove resource location element.");
                        }
                    }
                }
            }
            if (!resourceLocationsRemoved) {
                logger.error(
                        "Failed to update Firejack Platform Node cache. Resource Location for removal was not found.");
            }
        }
    }

    @Override
    public List<Action> getActions(String packageLookup) {
        List<Action> actions;
        if (StringUtils.isNotBlank(packageLookup)) {
            actions = CacheManager.getInstance().getActions(packageLookup);
        } else {
            actions = new LinkedList<Action>();
        }
        return actions;
    }

    @Override
    public void addAction(Action actionInfo) {
        if (actionInfo != null) {
            String packageLookup = getPackageLookup(actionInfo.getPath());
            if (StringUtils.isNotBlank(packageLookup)) {
                CacheManager cacheManager = CacheManager.getInstance();
                List<Action> actions = cacheManager.getActions(packageLookup);
                if (actions != null) {
                    actions.add(actionInfo);
                    cacheManager.setActions(packageLookup, actions);
                }
            }
        }
    }

    @Override
    public void addActions(List<Action> actions) {
        if (actions != null && !actions.isEmpty()) {
            Map<String, SortedSet<Action>> packageActions = new HashMap<String, SortedSet<Action>>();
            for (Action action : actions) {
                String packageLookup = getPackageLookup(action.getPath());
                SortedSet<Action> voList = packageActions.get(packageLookup);
                if (voList == null) {
                    voList = new TreeSet<Action>(new ActionComparator());
                    packageActions.put(packageLookup, voList);
                }
                voList.add(action);
            }
            CacheManager cacheManager = CacheManager.getInstance();
            for (Map.Entry<String, SortedSet<Action>> packageActionsEntry : packageActions.entrySet()) {

                List<Action> cachedActions = cacheManager.getActions(packageActionsEntry.getKey());
                if (cachedActions == null) {
                    cachedActions = new LinkedList<Action>();
                }
                for (Action action : packageActionsEntry.getValue()) {
                    cachedActions.add(action);
                }
                cacheManager.setActions(packageActionsEntry.getKey(), cachedActions);
            }
        }
    }

    @Override
    public void updateAction(Action actionInfo) {
        if (actionInfo != null) {
            String packageLookup = getPackageLookup(actionInfo.getPath());
            if (StringUtils.isNotBlank(packageLookup)) {
                boolean actionUpdated = false;
                CacheManager cacheManager = CacheManager.getInstance();
                List<Action> actions = cacheManager.getActions(packageLookup);
                if (actions != null) {
                    for (Action action : actions) {
                        if (action.getId().equals(actionInfo.getId())) {
                            actions.remove(action);
                            actions.add(actionInfo);
                            cacheManager.setActions(packageLookup, actions);
                            actionUpdated = true;
                            break;
                        }
                    }
                }
                if (!actionUpdated) {
                    logger.error("Failed to update Firejack Platform Node cache. Action for update [id = "
                            + actionInfo.getId() + "] was not found.");
                }
            }
        }
    }

    @Override
    public void removeAction(Action actionInfo) {
        if (actionInfo != null) {
            String packageLookup = getPackageLookup(actionInfo.getPath());
            if (StringUtils.isNotBlank(packageLookup)) {
                boolean actionRemoved = false;
                CacheManager cacheManager = CacheManager.getInstance();
                List<Action> actions = cacheManager.getActions(packageLookup);

                if (actions != null && actions.remove(actionInfo)) {
                    List<Action> actionList = new LinkedList<Action>(actions);
                    cacheManager.setActions(packageLookup, actionList);
                    actionRemoved = true;
                }
                if (!actionRemoved) {
                    logger.error(
                            "Failed to update Firejack Platform Node cache. Action for removal was not found.");
                }
            }
        }
    }

    @Override
    public void addUserContextPermissions(Long userId, Long securedRecordId, Long roleId, String entityType,
            String entityId, List<String> permissionLookups) {
        if (userId != null && roleId != null && permissionLookups != null && !permissionLookups.isEmpty()) {
            boolean securedRecordIsNull = securedRecordId == null;
            CacheManager cacheManager = CacheManager.getInstance();
            Long secRecordId = securedRecordIsNull ? EMPTY_SECURED_RECORD_ID : securedRecordId;
            SecuredRecordPermissions contextPermissionsByUsers = cacheManager
                    .getSecuredRecordPermissions(secRecordId);
            if (contextPermissionsByUsers == null) {
                contextPermissionsByUsers = new SecuredRecordPermissions(secRecordId,
                        new HashMap<Long, UserContextPermissions>());
            }
            UserContextPermissions userPermissionsByRoles = contextPermissionsByUsers.getUserContextPermissions()
                    .get(userId);
            if (userPermissionsByRoles == null) {
                userPermissionsByRoles = new UserContextPermissions(userId);
                contextPermissionsByUsers.getUserContextPermissions().put(userId, userPermissionsByRoles);
            }
            ContextPermissions contextRolePermissions = userPermissionsByRoles.getContextPermissions(roleId);
            if (contextRolePermissions == null) {
                contextRolePermissions = new ContextPermissions(roleId, entityType, entityId);
            } else {
                logger.warn("Context role permissions for [roleId = " + roleId + ", userId = " + userId
                        + "] already exist. Overriding the context role permissions...");
            }
            contextRolePermissions.setPermissions(permissionLookups);
            userPermissionsByRoles.putContextRolePermissions(contextRolePermissions);

            cacheManager.setSecuredRecordPermissions(secRecordId, contextPermissionsByUsers);

            //add id filters for user using specified context permission if necessary.
            addIdFiltersForContextPermissions(userId, contextRolePermissions.userPermissionsSnapshot());

            //update context permissions info in cache
            UserSessionManager userSessionManager = UserSessionManager.getInstance();
            if (securedRecordIsNull) {
                userSessionManager.addUserRole(userId, roleId, this);
            } else {
                //addSecuredRecordInheritedPermissionsForUser(userId, secRecordId, contextPermissions);

                Map<Long, Map<Long, List<UserPermission>>> userPermissionsBySecuredRecords = getUserPermissionsBySecuredRecords(
                        userId);
                userSessionManager.refreshUserContextRolePermissions(userId, userPermissionsBySecuredRecords);
            }
        }
    }

    @Override
    public void updatePackageLevelPermissions(String packageLookup, Long userId, Long roleId,
            List<String> permissionLookupList) {
        CacheManager cacheManager = CacheManager.getInstance();
        UserContextPermissions pkgLevelPermissions = cacheManager.getPackageLevelUserPermissions(packageLookup,
                userId);
        if (pkgLevelPermissions == null) {
            pkgLevelPermissions = new UserContextPermissions();
            pkgLevelPermissions.setRolePermissions(new HashMap<Long, List<UserPermission>>());
        }
        pkgLevelPermissions.getRolePermissions().put(roleId,
                AuthorizationVOFactory.convertPermissionsEx(permissionLookupList));
        cacheManager.setPackageLevelUserPermissions(packageLookup, userId, pkgLevelPermissions);
    }

    @Override
    public void deletePackageLevelPermissions(String packageLookup, Long userId, Long roleId) {
        CacheManager cacheManager = CacheManager.getInstance();
        UserContextPermissions pkgLevelPermissions = cacheManager.getPackageLevelUserPermissions(packageLookup,
                userId);
        if (pkgLevelPermissions != null) {
            pkgLevelPermissions.getRolePermissions().remove(roleId);
            cacheManager.setPackageLevelUserPermissions(packageLookup, userId, pkgLevelPermissions);
        }
    }

    @Override
    public void addUserContextPermissions(Long userId, Long roleId, String entityType, String entityId,
            List<String> permissionLookupList) {
        addUserContextPermissions(userId, null, roleId, entityType, entityId, permissionLookupList);
    }

    @Override
    public Map<Long, List<UserPermission>> getUserContextPermissions(Long userId) {
        Map<Long, List<UserPermission>> result = null;
        if (userId != null) {
            CacheManager cacheManager = CacheManager.getInstance();
            SecuredRecordPermissions contextPermissionsByUsers = cacheManager
                    .getSecuredRecordPermissions(EMPTY_SECURED_RECORD_ID);
            if (contextPermissionsByUsers != null) {
                UserContextPermissions userRolePermissions = contextPermissionsByUsers.getUserContextPermissions()
                        .get(userId);
                if (userRolePermissions != null) {
                    result = userRolePermissions.populateRolePermissions();
                }
            }
        }
        return result == null ? new HashMap<Long, List<UserPermission>>() : result;
    }

    @Override
    public Map<Long, Map<Long, List<UserPermission>>> getUserPermissionsBySecuredRecords(Long userId) {
        Map<Long, Map<Long, List<UserPermission>>> userContextPermissionsBySecuredRecords = new HashMap<Long, Map<Long, List<UserPermission>>>();
        if (userId != null) {
            CacheManager cacheManager = CacheManager.getInstance();
            Map<Long, SecuredRecordPermissions> cp = cacheManager.getAllSecuredRecordPermissions();
            for (SecuredRecordPermissions srPermissions : cp.values()) {
                if (!EMPTY_SECURED_RECORD_ID.equals(srPermissions.getSecuredRecordId())) {
                    UserContextPermissions userSecuredRecordPermission = srPermissions.getUserContextPermissions()
                            .get(userId);
                    if (userSecuredRecordPermission != null) {
                        userContextPermissionsBySecuredRecords.put(srPermissions.getSecuredRecordId(),
                                userSecuredRecordPermission.populateRolePermissions());
                    }
                }
            }
        }
        return userContextPermissionsBySecuredRecords;
    }

    @Override
    public void refreshSecuredRecords(Map<Long, SecuredRecordNode> securedRecords) {
        if (ConfigContainer.isAppInstalled()) {
            if (securedRecords != null) {
                CacheManager.getInstance().setSecuredRecords(securedRecords);
            }
        }
    }

    @Override
    public void addSecuredRecords(List<SecuredRecordNode> securedRecords) {
        if (ConfigContainer.isAppInstalled() && securedRecords != null) {
            Map<Long, SecuredRecordNode> allSR = CacheManager.getInstance().getSecuredRecords();
            allSR = allSR == null ? new HashMap<Long, SecuredRecordNode>() : allSR;
            for (SecuredRecordNode sr : securedRecords) {
                if (sr.getSecuredRecordId() != null) {
                    if (!allSR.containsKey(sr.getSecuredRecordId())) {
                        allSR.put(sr.getSecuredRecordId(), sr);
                    }
                }
            }
            CacheManager.getInstance().setSecuredRecords(allSR);
        }
    }

    @Override
    public void addSecuredRecord(SecuredRecordNode securedRecord) {
        if (ConfigContainer.isAppInstalled() && securedRecord != null
                && securedRecord.getSecuredRecordId() != null) {
            Map<Long, SecuredRecordNode> allSR = CacheManager.getInstance().getSecuredRecords();
            allSR = allSR == null ? new HashMap<Long, SecuredRecordNode>() : allSR;
            if (!allSR.containsKey(securedRecord.getSecuredRecordId())) {
                allSR.put(securedRecord.getSecuredRecordId(), securedRecord);
            }
            CacheManager.getInstance().setSecuredRecords(allSR);
        }
    }

    @Override
    public void deleteSecuredRecord(Long securedRecordId) {
        if (ConfigContainer.isAppInstalled() && securedRecordId != null) {
            Map<Long, SecuredRecordNode> allSR = CacheManager.getInstance().getSecuredRecords();
            allSR = allSR == null ? new HashMap<Long, SecuredRecordNode>() : allSR;
            allSR.remove(securedRecordId);
            CacheManager.getInstance().setSecuredRecords(allSR);
        }
    }

    @Override
    public void deleteSecuredRecords(List<Long> securedRecordIdList) {
        if (ConfigContainer.isAppInstalled() && securedRecordIdList != null && !securedRecordIdList.isEmpty()) {
            Map<Long, SecuredRecordNode> allSR = CacheManager.getInstance().getSecuredRecords();
            allSR = allSR == null ? new HashMap<Long, SecuredRecordNode>() : allSR;
            for (Long securedRecordId : securedRecordIdList) {
                allSR.remove(securedRecordId);
            }
            CacheManager.getInstance().setSecuredRecords(allSR);
        }
    }

    @Override
    public Map<String, IdFilter> getFiltersByUser(Long userId) {
        Map<String, IdFilter> result;
        if (userId == null) {
            result = Collections.emptyMap();
        } else {
            result = CacheManager.getInstance().getIdFiltersForUser(userId);
            result = result == null ? Collections.<String, IdFilter>emptyMap() : result;
        }
        return result;
    }

    @Override
    public void associatePermissionWithAction(String actionLookup, Permission permission) {
        if (StringUtils.isBlank(actionLookup) || permission == null) {
            logger.error(StringUtils.isBlank(actionLookup) ? "Action Lookup should not be blank."
                    : "Permission Lookup should not be blank.");
        } else {
            String packageLookup = getPackageLookup(actionLookup);
            CacheManager cacheManager = CacheManager.getInstance();
            List<Action> packageActions = cacheManager.getActions(packageLookup);

            if (packageActions == null) {
                logger.error("Actions for considered package has not registered yet.");
            } else {
                boolean notFound = true;
                for (Action action : packageActions) {
                    if (actionLookup.equals(action.getLookup())) {
                        notFound = false;
                        List<Permission> permissions = action.getPermissions();
                        if (permissions == null) {
                            permissions = new ArrayList<Permission>();
                        }
                        if (!permissions.contains(permission)) {
                            permissions.add(permission);
                            action.setPermissions(permissions);
                            cacheManager.setActions(packageLookup, packageActions);
                            break;
                        }
                    }
                }
                if (notFound) {
                    logger.error("Target action that should be used to associate permission with was not found.");
                }
            }
        }
    }

    @Override
    public void associatePermissionWithNavigation(String navigationLookup, Permission permission) {
        if (StringUtils.isBlank(navigationLookup) || permission == null) {
            logger.error(StringUtils.isBlank(navigationLookup) ? "Navigation Element Lookup should not be blank."
                    : "Permission Lookup should not be blank.");
        } else {
            String packageLookup = getPackageLookup(navigationLookup);
            CacheManager cacheManager = CacheManager.getInstance();
            List<NavigationElement> packageNavigations = cacheManager.getNavigationList(packageLookup);
            if (packageNavigations == null) {
                logger.error("Navigation Elements for considered package has not registered yet.");
            } else {
                boolean notFound = true;
                for (NavigationElement nav : packageNavigations) {
                    if (navigationLookup.equals(nav.getLookup())) {
                        notFound = false;
                        List<Permission> permissions = nav.getPermissions();
                        if (permissions == null) {
                            permissions = new ArrayList<Permission>();
                        }
                        if (!permissions.contains(permission)) {
                            permissions.add(permission);
                            nav.setPermissions(permissions);
                            cacheManager.setNavigationList(packageLookup, packageNavigations);
                            break;
                        }
                    }
                }
                if (notFound) {
                    logger.error("Target action that should be used to associate permission with was not found.");
                }
            }
        }
    }

    @Override
    public void associatePermissionWithResourceLocation(String resourceLocationLookup, Permission permission) {
        if (StringUtils.isBlank(resourceLocationLookup) || permission == null) {
            logger.error(
                    StringUtils.isBlank(resourceLocationLookup) ? "Navigation Element Lookup should not be blank."
                            : "Permission Lookup should not be blank.");
        } else {
            String packageLookup = getPackageLookup(resourceLocationLookup);
            CacheManager cacheManager = CacheManager.getInstance();
            List<ResourceLocation> packageResourceLocations = cacheManager.getResourceLocations(packageLookup);
            if (packageResourceLocations == null) {
                logger.error("Navigation Elements for considered package has not registered yet.");
            } else {
                boolean notFound = true;
                for (ResourceLocation resourceLocation : packageResourceLocations) {
                    if (resourceLocationLookup.equals(resourceLocation.getLookup())) {
                        notFound = false;
                        List<Permission> permissions = resourceLocation.getPermissions();
                        if (permissions == null) {
                            permissions = new ArrayList<Permission>();
                        }
                        if (!permissions.contains(permission)) {
                            permissions.add(permission);
                            resourceLocation.setPermissions(permissions);
                            cacheManager.setResourceLocations(packageLookup, packageResourceLocations);
                            break;
                        }
                    }
                }
                if (notFound) {
                    logger.error("Target action that should be used to associate permission with was not found.");
                }
            }
        }
    }

    @Override
    public void saveNewEntity(Entity entity) {
        if (entity != null) {
            List<Entity> entityList = new ArrayList<Entity>();
            entityList.add(entity);
            CacheManager cacheManager = CacheManager.getInstance();
            cacheManager.setTypeWithSubclasses(entity.getLookup(), entityList);
            List<String> entityTypes = cacheManager.getEntityTypes();
            if (entityTypes == null) {
                logger.error("No entity types found in cache.");
            } else {
                entityTypes.add(entity.getLookup());
                cacheManager.setEntityTypes(entityTypes);
            }
            Boolean securityEnabled = entity.getSecurityEnabled();
            cacheManager.setEntityAsSecurityEnabled(entity.getLookup(), securityEnabled != null && securityEnabled);
        }
    }

    @Override
    public void saveEntity(Entity entity) {
        if (entity != null) {
            CacheManager cacheManager = CacheManager.getInstance();
            List<String> entityTypes = cacheManager.getEntityTypes();
            if (entityTypes == null) {
                logger.error("No entity types found in cache.");
            } else {
                for (String typeLookup : entityTypes) {
                    List<Entity> typeWithSubclasses = cacheManager.getTypeWithSubclasses(typeLookup);
                    if (typeWithSubclasses == null) {
                        logger.error("Type [" + typeLookup + "] was not found in cache.");
                    } else {
                        for (Entity type : typeWithSubclasses) {
                            if (type.getId().equals(entity.getId())) {
                                typeWithSubclasses.remove(type);
                                typeWithSubclasses.add(entity);
                                cacheManager.setTypeWithSubclasses(typeLookup, typeWithSubclasses);
                                break;
                            }
                        }
                    }
                }
            }
            Boolean securityEnabled = entity.getSecurityEnabled();
            cacheManager.setEntityAsSecurityEnabled(entity.getLookup(), securityEnabled != null && securityEnabled);
        }
    }

    @Override
    public void updateEntityLookup(String oldLookup, String newLookup) {
        if (StringUtils.isBlank(oldLookup) || StringUtils.isBlank(newLookup)) {
            logger.warn("Lookup parameters for entity to update could not be blank.");
        } else {
            CacheManager cacheManager = CacheManager.getInstance();
            List<String> entityTypes = cacheManager.getEntityTypes();

            boolean typeNotUpdated = true;
            for (String typeLookup : entityTypes) {
                List<Entity> typeWithSubclasses = cacheManager.getTypeWithSubclasses(typeLookup);
                boolean updated = false;
                if (typeWithSubclasses == null) {
                    logger.error("Type [" + typeLookup + "] was not found in cache.");
                } else {
                    for (Entity entity : typeWithSubclasses) {
                        if (oldLookup.equals(entity.getLookup())) {
                            //we don't care about other properties of entity, take care only for lookup
                            entity.setLookup(newLookup);
                            updated = true;
                            break;
                        }
                    }
                }
                if (oldLookup.equals(typeLookup)) {
                    if (updated) {
                        cacheManager.removeTypeWithSubclasses(oldLookup);
                        cacheManager.setTypeWithSubclasses(newLookup, typeWithSubclasses);
                        typeNotUpdated = false;
                    } else {
                        logger.warn("Entity Lookup was not updated for type = [" + oldLookup + "]");
                    }
                } else if (updated) {
                    cacheManager.setTypeWithSubclasses(oldLookup, typeWithSubclasses);
                }
            }
            if (typeNotUpdated) {
                logger.error("Type [" + oldLookup + "] was not found in cache.");
                List<Entity> typeWithSubclasses = cacheManager.getTypeWithSubclasses(oldLookup);
                if (typeWithSubclasses == null) {
                    logger.error("Cached type was not found.");
                } else {
                    for (Entity entity : typeWithSubclasses) {
                        if (oldLookup.equals(entity.getLookup())) {
                            //we don't care about other properties of entity, take care only for lookup
                            entity.setLookup(newLookup);
                            break;
                        }
                    }
                    cacheManager.setTypeWithSubclasses(newLookup, typeWithSubclasses);
                }
            }

            entityTypes.remove(oldLookup);
            entityTypes.add(newLookup);
            cacheManager.setEntityTypes(entityTypes);
        }
    }

    @Override
    public void updateExtendedEntity(String entityToUpdate, String newExtendedEntity) {
        if (StringUtils.isNotBlank(entityToUpdate)) {
            CacheManager cacheManager = CacheManager.getInstance();
            List<String> entityTypes = cacheManager.getEntityTypes();
            if (entityTypes == null) {
                logger.error("No entity types found in cache.");
            } else {
                Map<String, List<Entity>> typesIncludesOldSuperType = new HashMap<String, List<Entity>>();
                Map<String, List<Entity>> typesIncludesNewSuperType = new HashMap<String, List<Entity>>();
                List<Entity> oldExtendedTypeEntities = null;
                Entity entityToChange = null;
                List<Entity> newExtendedTypeEntities = null;
                for (String type : entityTypes) {
                    List<Entity> typeWithSubclasses = cacheManager.getTypeWithSubclasses(type);
                    if (type.equals(entityToUpdate)) {
                        oldExtendedTypeEntities = typeWithSubclasses;
                        if (oldExtendedTypeEntities == null) {
                            break;
                        } else {
                            for (Entity entity : oldExtendedTypeEntities) {
                                if (entity.getLookup().equals(entityToUpdate)) {
                                    entityToChange = entity;
                                    break;
                                }
                            }
                        }
                    } else if (type.equals(newExtendedEntity)) {
                        newExtendedTypeEntities = typeWithSubclasses;
                        if (newExtendedTypeEntities == null) {
                            break;
                        }
                    } else if (typeWithSubclasses != null) {
                        boolean oldExtendedEntityFound = false;
                        boolean newExtendedEntityFound = false;
                        for (Entity entity : typeWithSubclasses) {
                            if (entity.getLookup().equals(entityToUpdate)) {
                                oldExtendedEntityFound = true;
                            } else if (entity.getLookup().equals(newExtendedEntity)) {
                                newExtendedEntityFound = true;
                            }
                            if (oldExtendedEntityFound && newExtendedEntityFound) {
                                break;
                            }
                        }
                        if (oldExtendedEntityFound) {
                            typesIncludesOldSuperType.put(type, typeWithSubclasses);
                        }
                        if (newExtendedEntityFound) {
                            typesIncludesNewSuperType.put(type, typeWithSubclasses);
                        }
                    }
                }
                if (oldExtendedTypeEntities == null || entityToChange == null) {
                    logger.error("Could not find old extended entity.");
                } else if (newExtendedTypeEntities == null) {
                    logger.error("Could not find changed extended entity.");
                } else {
                    for (Map.Entry<String, List<Entity>> entry : typesIncludesOldSuperType.entrySet()) {
                        entry.getValue().removeAll(oldExtendedTypeEntities);
                    }
                    for (Map.Entry<String, List<Entity>> entry : typesIncludesNewSuperType.entrySet()) {
                        entry.getValue().addAll(newExtendedTypeEntities);
                        if (!typesIncludesOldSuperType.containsKey(entry.getKey())) {
                            typesIncludesOldSuperType.put(entry.getKey(), entry.getValue());
                        }
                    }
                    for (Map.Entry<String, List<Entity>> entry : typesIncludesOldSuperType.entrySet()) {
                        cacheManager.setTypeWithSubclasses(entry.getKey(), entry.getValue());
                    }
                }
            }
        }
    }

    @Override
    public void deleteEntityByLookup(String entityLookup) {
        if (StringUtils.isNotBlank(entityLookup)) {
            CacheManager cacheManager = CacheManager.getInstance();
            List<String> entityTypes = cacheManager.getEntityTypes();
            if (entityTypes == null) {
                logger.error("No entity types found in cache.");
            } else {
                boolean typeNotRemoved = true;
                for (String typeLookup : entityTypes) {
                    if (entityLookup.equalsIgnoreCase(typeLookup)) {
                        cacheManager.removeTypeWithSubclasses(typeLookup);
                        typeNotRemoved = false;
                    } else {
                        List<Entity> typeWithSubclasses = cacheManager.getTypeWithSubclasses(typeLookup);
                        if (typeWithSubclasses != null) {
                            for (Entity entity : typeWithSubclasses) {
                                if (entityLookup.equals(entity.getLookup())) {
                                    typeWithSubclasses.remove(entity);
                                    break;
                                }
                            }
                        }
                    }
                }
                if (typeNotRemoved) {
                    logger.warn("Type [" + entityLookup + "] was not found in cache.");
                    cacheManager.removeTypeWithSubclasses(entityLookup);
                }
                entityTypes.remove(entityLookup);
                cacheManager.setEntityTypes(entityTypes);
            }
        }
    }

    private Map<String, IdFilter> getUserIdFilters(Long userId) {
        CacheManager cacheManager = CacheManager.getInstance();
        Map<String, IdFilter> userFilters = cacheManager.getIdFiltersForUser(userId);
        if (userFilters == null || userFilters.getClass().equals(Collections.emptyMap().getClass())) {
            userFilters = new HashMap<String, IdFilter>();
            cacheManager.setIdFiltersForUser(userId, userFilters);
        }
        return userFilters;
    }

    private void updateIdFiltersOnRolesChange(Long userId, List<Long> roleIdList) {
        Set<String> newTypes = new HashSet<String>();
        CacheManager cacheManager = CacheManager.getInstance();
        for (Long roleId : roleIdList) {
            List<UserPermission> userPermissions = cacheManager.getRolePermissions(roleId);
            if (userPermissions != null) {
                for (UserPermission permission : userPermissions) {
                    String entityType;
                    if ((entityType = getReadPermissionType(permission)) != null) {
                        newTypes.add(entityType);
                    }
                }
            }
        }
        Map<String, IdFilter> userFilters = getUserIdFilters(userId);
        boolean changed = false;
        for (Map.Entry<String, IdFilter> entry : userFilters.entrySet()) {
            if (newTypes.contains(entry.getKey())) {
                if (!entry.getValue().isGlobalPermissionGranted()) {
                    entry.getValue().setGlobalPermissionGranted(true);
                    changed = true;
                }
            } else if (entry.getValue().isGlobalPermissionGranted()) {
                entry.getValue().setGlobalPermissionGranted(false);
                changed = true;
            }
        }
        for (String type : newTypes) {
            if (!userFilters.keySet().contains(type)) {
                IdFilter filter = new IdFilter();
                filter.setGlobalPermissionGranted(true);
                userFilters.put(type, filter);
                changed = true;
            }
        }
        if (changed) {
            CacheManager.getInstance().setIdFiltersForUser(userId, userFilters);
        }
    }

    private String getReadPermissionType(UserPermission userPermission) {
        return userPermission == null ? null : getReadPermissionType(userPermission.getPermission());
    }

    private String getReadPermissionType(String userPermission) {
        String entityType;
        if (ActionDetectorFactory.isReadPermission(userPermission)
                || ActionDetectorFactory.isReadAllPermission(userPermission)) {
            entityType = ActionDetectorFactory.isReadPermission(userPermission)
                    ? ActionDetectorFactory.getReadPermissionType(userPermission)
                    : ActionDetectorFactory.getReadAllPermissionType(userPermission);
        } else {
            entityType = null;
        }
        return entityType;
    }

    private void addIdFiltersForContextPermissions(Long userId, List<UserPermission> contextPermissions) {
        CacheManager cacheManager = CacheManager.getInstance();
        Map<String, IdFilter> idFilters = null;
        for (UserPermission contextPermission : contextPermissions) {
            if (ActionDetectorFactory.isReadPermissionForType(contextPermission)) {
                idFilters = cacheManager.getIdFiltersForUser(userId);
                if (idFilters == null) {
                    idFilters = new HashMap<String, IdFilter>();
                }
                String entityType = contextPermission.getEntityType();
                IdFilter idFilter = idFilters.get(entityType);
                if (idFilter == null) {
                    idFilter = new IdFilter();
                    idFilters.put(entityType, idFilter);
                }
                idFilter.grantId(Long.parseLong(contextPermission.getEntityId()));
            }
        }
        if (idFilters != null) {
            cacheManager.setIdFiltersForUser(userId, idFilters);
        }
    }

    private Map<Long, UserContextPermissions> getContextPermissionsByUsers(List<UserRoleModel> userRoles) {
        //populate map of available UserPermissions by user for considered secured record
        Map<Long, UserContextPermissions> contextPermissionsByUsers = new HashMap<Long, UserContextPermissions>();
        for (UserRoleModel userRole : userRoles) {
            Long userId = userRole.getUser().getId();
            UserContextPermissions userPermissions = contextPermissionsByUsers.get(userId);
            if (userPermissions == null) {
                userPermissions = new UserContextPermissions(userId);
                contextPermissionsByUsers.put(userId, userPermissions);
            }

            ContextPermissions contextPermissions = new ContextPermissions(userRole.getRole().getId(),
                    userRole.getType(), userRole.getInternalId().toString());
            contextPermissions
                    .setPermissions(AuthorizationVOFactory.retrieveLookupList(userRole.getRole().getPermissions()));
            userPermissions.putContextRolePermissions(contextPermissions);
        }
        return contextPermissionsByUsers;
    }

    private String getPackageLookup(String actionPath) {
        String[] actionPathEntries = actionPath.split("\\.");
        if (actionPathEntries == null || actionPathEntries.length < 3) {
            throw new IllegalStateException("Failed to process lookup of action's package: " + actionPath);
        }
        return StringUtils.join(new String[] { actionPathEntries[0], actionPathEntries[1], actionPathEntries[2] },
                ".");
    }

    private Map<Long, Map<String, IdFilter>> populateReadActionFiltersInfo(//todo: check
            Map<Long, SecuredRecordPermissions> securedRecordPermissions,
            Map<Long, List<UserPermission>> permissionsByRoles, Map<Long, List<Long>> userRoles) {
        Map<Long, Map<String, IdFilter>> filtersByUser = new HashMap<Long, Map<String, IdFilter>>();

        //populate id-filters with global permissions first
        for (Map.Entry<Long, List<UserPermission>> userPermissionsByRole : permissionsByRoles.entrySet()) {
            Long roleId = userPermissionsByRole.getKey();
            for (UserPermission userPermission : userPermissionsByRole.getValue()) {
                if (userPermission.getPermission().endsWith(".read-all")) {
                    String entityType = userPermission.getPermission().substring(0,
                            userPermission.getPermission().length() - ".read-all".length());

                    for (Map.Entry<Long, List<Long>> userRolesEntry : userRoles.entrySet()) {
                        Long userId = userRolesEntry.getKey();
                        List<Long> roleIdList = userRolesEntry.getValue();
                        if (roleIdList.contains(roleId)) {
                            IdFilter filterInfo;
                            Map<String, IdFilter> userFiltersByTypes = filtersByUser.get(userId);
                            if (userFiltersByTypes == null) {
                                userFiltersByTypes = new HashMap<String, IdFilter>();
                                filtersByUser.put(userId, userFiltersByTypes);
                                filterInfo = null;
                            } else {
                                filterInfo = userFiltersByTypes.get(entityType);
                            }
                            if (filterInfo == null) {
                                filterInfo = new IdFilter();
                                userFiltersByTypes.put(entityType, filterInfo);
                            }
                            filterInfo.setGlobalPermissionGranted(Boolean.TRUE);//todo:check
                            break;
                        }
                    }
                }
            }
        }
        for (SecuredRecordPermissions contextRolePermissionsByUser : securedRecordPermissions.values()) {
            for (Map.Entry<Long, UserContextPermissions> contextRolePermissionsByUserEntry : contextRolePermissionsByUser
                    .getUserContextPermissions().entrySet()) {

                Long userId = contextRolePermissionsByUserEntry.getKey();

                Map<String, IdFilter> filtersByEntityType = filtersByUser.get(userId);
                if (filtersByEntityType == null) {
                    filtersByEntityType = new HashMap<String, IdFilter>();
                    filtersByUser.put(userId, filtersByEntityType);
                }

                UserContextPermissions userContextPermissions = contextRolePermissionsByUserEntry.getValue();
                for (List<UserPermission> rolePermissions : userContextPermissions.populateRolePermissions()
                        .values()) {
                    for (UserPermission userPermission : rolePermissions) {
                        //if (userPermission.getPermission().endsWith(".read")) {
                        if (ActionDetectorFactory.isReadPermissionForType(userPermission)) {
                            IdFilter idFilterInfo = filtersByEntityType.get(userPermission.getEntityType());
                            if (idFilterInfo == null) {
                                idFilterInfo = new IdFilter();
                                filtersByEntityType.put(userPermission.getEntityType(), idFilterInfo);
                            }
                            if (!idFilterInfo.isGlobalPermissionGranted()) {
                                Long id = Long.valueOf(userPermission.getEntityId());
                                idFilterInfo.grantId(id);
                            } //else filter already exist and has filter.setAll(Boolean.TRUE), so context roles do not considered
                              //todo: process DENY version
                        }
                    }
                }
            }
        }
        return filtersByUser;
    }

    private Map<Long, SecuredRecordPermissions> retrieveSecuredRecordPermissions() {
        //process context user permissions
        Map<SecuredRecordModel, List<UserRoleModel>> securedRecordContextRoles = userRoleStore
                .findAllContextRolesBySecuredRecords();
        Map<Long, SecuredRecordPermissions> securedRecordPermissions = new HashMap<Long, SecuredRecordPermissions>();
        if (securedRecordContextRoles != null) {
            for (Map.Entry<SecuredRecordModel, List<UserRoleModel>> securedRecordEntry : securedRecordContextRoles
                    .entrySet()) {
                Long securedRecordId = securedRecordEntry.getKey().getId();

                /*Map<Long, UserContextPermissions> contextPermissionsByUsers = getContextPermissionsByUsers(
                                        securedRecordEntry.getValue(), srPathsHelper, securedRecordContextRoles);*/
                Map<Long, UserContextPermissions> contextPermissionsByUsers = getContextPermissionsByUsers(
                        securedRecordEntry.getValue());
                securedRecordPermissions.put(securedRecordId,
                        new SecuredRecordPermissions(securedRecordId, contextPermissionsByUsers));
            }
        }
        //if contextual roles not bound to any secured record were found, then put them into store and assign them to fake secured record id EMPTY_SECURED_RECORD_ID
        List<UserRoleModel> usualContextRoles = userRoleStore.findAllContextRolesNotBoundToSecuredRecord();
        if (usualContextRoles != null) {
            /*Map<Long, UserContextPermissions> contextPermissionsByUsersEx = getContextPermissionsByUsers(usualContextRoles, null, null);*/
            Map<Long, UserContextPermissions> contextPermissionsByUsersEx = getContextPermissionsByUsers(
                    usualContextRoles);
            securedRecordPermissions.put(EMPTY_SECURED_RECORD_ID,
                    new SecuredRecordPermissions(EMPTY_SECURED_RECORD_ID, contextPermissionsByUsersEx));
        }
        return securedRecordPermissions;
    }

    private Map<Long, List<UserPermission>> retrieveGlobalPermissions(List<RoleModel> roles) {
        List<Long> globalRoleIdList = new ArrayList<Long>();
        for (RoleModel role : roles) {
            if (role.isGlobal()) {
                globalRoleIdList.add(role.getId());
            }
        }
        Map<Long, List<PermissionModel>> permissionsByRoleMap = permissionStore
                .findRolePermissions(globalRoleIdList);
        Map<Long, List<UserPermission>> permissionsByRoles = new HashMap<Long, List<UserPermission>>();
        for (Map.Entry<Long, List<PermissionModel>> rolePermissions : permissionsByRoleMap.entrySet()) {
            List<PermissionModel> permissions = rolePermissions.getValue();
            List<UserPermission> permissionList = new LinkedList<UserPermission>();
            for (PermissionModel permission : permissions) {
                permissionList.add(new UserPermission(permission.getLookup()));
            }
            permissionsByRoles.put(rolePermissions.getKey(), permissionList);
        }
        return permissionsByRoles;
    }

    private Map<String, PackageModel> retrievePackageByLookup() {
        //load package lookup list
        List<PackageModel> packageList = packageStore.findAll();
        Map<String, PackageModel> pkgByLookup = new HashMap<String, PackageModel>();
        if (packageList != null) {
            for (PackageModel p : packageList) {
                pkgByLookup.put(p.getLookup(), p);
            }
        }
        return pkgByLookup;
    }

    private Map<String, List<NavigationElement>> retrieveNavigationElementsByPackage(
            List<String> packageLookupList) {
        //process navigation elements
        Map<String, List<NavigationElement>> packageNavigationElements = new HashMap<String, List<NavigationElement>>();
        for (String packageLookup : packageLookupList) {
            List<NavigationElementModel> navElements = navigationElementStore.findAllWithPermissions(packageLookup);
            List<NavigationElement> navigationList = this.modelFactory.convertTo(NavigationElement.class,
                    navElements);
            packageNavigationElements.put(packageLookup, navigationList);
        }
        return packageNavigationElements;
    }

    private Map<String, SortedSet<Action>> retrieveActionsByPackage() {
        //process actions
        Map<String, List<ActionModel>> actionList = actionStore.findAllWithPermissionsByPackage();
        Map<String, SortedSet<Action>> actionsMap = new HashMap<String, SortedSet<Action>>();
        for (Map.Entry<String, List<ActionModel>> packageActions : actionList.entrySet()) {
            if (packageActions.getValue() != null) {
                SortedSet<Action> actionSet = new TreeSet<Action>(new ActionComparator());
                for (ActionModel action : packageActions.getValue()) {
                    Action actionInfo = modelFactory.convertTo(Action.class, action);
                    actionSet.add(actionInfo);
                }
                actionsMap.put(packageActions.getKey(), actionSet);
            }
        }
        return actionsMap;
    }

    private Map<String, List<ResourceLocation>> retrieveResourceLocationsByPackage(List<String> packageLookupList) {
        //process resource locations
        Map<String, List<ResourceLocation>> resourceLocations = new HashMap<String, List<ResourceLocation>>();
        for (String packageLookup : packageLookupList) {
            List<ResourceLocationModel> resourceLocationList = resourceLocationStore
                    .findAllWithPermissions(packageLookup);
            List<ResourceLocation> maskedResourceVOList = modelFactory.convertTo(ResourceLocation.class,
                    resourceLocationList);
            resourceLocations.put(packageLookup, maskedResourceVOList);
        }
        return resourceLocations;
    }

    private Map<Long, SecuredRecordNode> retrieveSecuredRecords() {
        List<SecuredRecordModel> securedRecordList = securedRecordStore.findAllWithLoadedRegistryNode();
        return AuthorizationVOFactory.convertSecuredRecords(securedRecordList);
    }

    private Map<String, List<Entity>> retrieveEntityUpHierarchies() {
        Map<String, List<EntityModel>> entitiesUpHierarchies = entityStore.findAllEntitiesUpHierarchies();
        Map<String, List<Entity>> entitiesMap = new HashMap<String, List<Entity>>();
        for (Map.Entry<String, List<EntityModel>> entry : entitiesUpHierarchies.entrySet()) {
            entitiesMap.put(entry.getKey(), this.modelFactory.convertTo(Entity.class, entry.getValue()));
        }
        return entitiesMap;
    }

    private Map<String, Map<Long, UserContextPermissions>> retrievePackageLevelUserPermissions() {
        Map<String, List<UserRoleModel>> userRolesByPackage = userRoleStore.findAllPackageLevelUserRoles();
        Map<String, Map<Long, UserContextPermissions>> result = new HashMap<String, Map<Long, UserContextPermissions>>();
        if (userRolesByPackage != null && !userRolesByPackage.isEmpty()) {
            for (Map.Entry<String, List<UserRoleModel>> entry : userRolesByPackage.entrySet()) {
                String packageLookup = entry.getKey();
                List<UserRoleModel> userRoles = entry.getValue();
                Map<Long, UserContextPermissions> userPermissions = new HashMap<Long, UserContextPermissions>();
                for (UserRoleModel userRole : userRoles) {
                    Long userId = userRole.getUser().getId();
                    UserContextPermissions userContextPermissions = userPermissions.get(userId);
                    if (userContextPermissions == null) {
                        userContextPermissions = new UserContextPermissions();
                        userContextPermissions.setRolePermissions(new HashMap<Long, List<UserPermission>>());
                        userPermissions.put(userId, userContextPermissions);
                    }
                    Long roleId = userRole.getRole().getId();
                    List<UserPermission> rolePermissions = AuthorizationVOFactory
                            .convertPermissions(userRole.getRole().getPermissions());
                    userContextPermissions.getRolePermissions().put(roleId, rolePermissions);
                }
                result.put(packageLookup, userPermissions);
            }
        }
        return result;
    }

}