/*
 * 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 org.apache.ranger.biz;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.ranger.common.ContextUtil;
import org.apache.ranger.common.GUIDUtil;
import org.apache.ranger.common.RangerCommonEnums;
import org.apache.ranger.entity.XXGroupPermission;
import org.apache.ranger.entity.XXModuleDef;
import org.apache.ranger.entity.XXUserPermission;
import org.apache.ranger.plugin.model.RangerPolicy;
import org.apache.ranger.plugin.model.RangerPolicy.RangerDataMaskPolicyItem;
import org.apache.ranger.plugin.model.RangerPolicy.RangerPolicyItem;
import org.apache.ranger.plugin.model.RangerPolicy.RangerRowFilterPolicyItem;
import org.apache.ranger.service.RangerPolicyService;
import org.apache.ranger.service.XGroupPermissionService;
import org.apache.ranger.service.XModuleDefService;
import org.apache.ranger.service.XPortalUserService;
import org.apache.ranger.service.XResourceService;
import org.apache.ranger.service.XUserPermissionService;
import org.apache.ranger.view.VXGroupPermission;
import org.apache.ranger.view.VXModuleDef;
import org.apache.ranger.view.VXUserPermission;
import org.apache.log4j.Logger;
import org.apache.ranger.authorization.utils.StringUtil;
import org.apache.ranger.common.AppConstants;
import org.apache.ranger.common.MessageEnums;
import org.apache.ranger.common.PropertiesUtil;
import org.apache.ranger.common.RangerConstants;
import org.apache.ranger.common.RangerServicePoliciesCache;
import org.apache.ranger.common.SearchCriteria;
import org.apache.ranger.common.UserSessionBase;
import org.apache.ranger.db.RangerDaoManager;
import org.apache.ranger.db.XXAuditMapDao;
import org.apache.ranger.db.XXAuthSessionDao;
import org.apache.ranger.db.XXGroupDao;
import org.apache.ranger.db.XXGroupGroupDao;
import org.apache.ranger.db.XXGroupPermissionDao;
import org.apache.ranger.db.XXGroupUserDao;
import org.apache.ranger.db.XXPermMapDao;
import org.apache.ranger.db.XXPolicyDao;
import org.apache.ranger.db.XXPortalUserDao;
import org.apache.ranger.db.XXPortalUserRoleDao;
import org.apache.ranger.db.XXResourceDao;
import org.apache.ranger.db.XXUserDao;
import org.apache.ranger.db.XXUserPermissionDao;
import org.apache.ranger.entity.XXAuditMap;
import org.apache.ranger.entity.XXAuthSession;
import org.apache.ranger.entity.XXGroup;
import org.apache.ranger.entity.XXGroupGroup;
import org.apache.ranger.entity.XXGroupUser;
import org.apache.ranger.entity.XXPermMap;
import org.apache.ranger.entity.XXPolicy;
import org.apache.ranger.entity.XXPortalUser;
import org.apache.ranger.entity.XXResource;
import org.apache.ranger.entity.XXTrxLog;
import org.apache.ranger.entity.XXUser;
import org.apache.ranger.service.XGroupService;
import org.apache.ranger.service.XUserService;
import org.apache.ranger.view.VXAuditMap;
import org.apache.ranger.view.VXAuditMapList;
import org.apache.ranger.view.VXGroup;
import org.apache.ranger.view.VXGroupGroup;
import org.apache.ranger.view.VXGroupList;
import org.apache.ranger.view.VXGroupUser;
import org.apache.ranger.view.VXGroupUserInfo;
import org.apache.ranger.view.VXGroupUserList;
import org.apache.ranger.view.VXLong;
import org.apache.ranger.view.VXPermMap;
import org.apache.ranger.view.VXPermMapList;
import org.apache.ranger.view.VXPortalUser;
import org.apache.ranger.view.VXUser;
import org.apache.ranger.view.VXUserGroupInfo;
import org.apache.ranger.view.VXUserList;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;

import org.apache.ranger.view.VXResponse;
import org.apache.ranger.entity.XXPortalUserRole;
import org.apache.ranger.view.VXString;
import org.apache.ranger.view.VXStringList;
@Component
public class XUserMgr extends XUserMgrBase {

	@Autowired
	XUserService xUserService;

	@Autowired
	XGroupService xGroupService;

	@Autowired
	RangerBizUtil msBizUtil;

	@Autowired
	UserMgr userMgr;

	@Autowired
	RangerDaoManager daoManager;

	@Autowired
	RangerBizUtil xaBizUtil;

	@Autowired
	XModuleDefService xModuleDefService;

	@Autowired
	XUserPermissionService xUserPermissionService;

	@Autowired
	XGroupPermissionService xGroupPermissionService;

	@Autowired
	XPortalUserService xPortalUserService;
	
	@Autowired
	XResourceService xResourceService;

	@Autowired
	SessionMgr sessionMgr;

	@Autowired
	RangerPolicyService policyService;

	@Autowired
	ServiceDBStore svcStore;

	@Autowired
	GUIDUtil guidUtil;

        @Autowired
        UserMgr userManager;

	static final Logger logger = Logger.getLogger(XUserMgr.class);



	public VXUser getXUserByUserName(String userName) {
		VXUser vXUser=null;
		vXUser=xUserService.getXUserByUserName(userName);
		if(vXUser!=null && !hasAccessToModule(RangerConstants.MODULE_USER_GROUPS)){
			vXUser=getMaskedVXUser(vXUser);
		}
		return vXUser;
	}

	public VXGroup getGroupByGroupName(String groupName) {
		VXGroup vxGroup = xGroupService.getGroupByGroupName(groupName);
		if (vxGroup == null) {
			throw restErrorUtil.createRESTException(
					groupName + " is Not Found", MessageEnums.DATA_NOT_FOUND);
		}
		return vxGroup;
	}

	public VXUser createXUser(VXUser vXUser) {
		checkAdminAccess();
                validatePassword(vXUser);
		String userName = vXUser.getName();
		if (userName == null || "null".equalsIgnoreCase(userName)
				|| userName.trim().isEmpty()) {
			throw restErrorUtil.createRESTException(
					"Please provide a valid username.",
					MessageEnums.INVALID_INPUT_DATA);
		}

		if (vXUser.getDescription() == null) {
			setUserDesc(vXUser);
		}

		String actualPassword = vXUser.getPassword();

		VXPortalUser vXPortalUser = new VXPortalUser();
		vXPortalUser.setLoginId(userName);
		vXPortalUser.setFirstName(vXUser.getFirstName());
		if("null".equalsIgnoreCase(vXPortalUser.getFirstName())){
			vXPortalUser.setFirstName("");
		}
		vXPortalUser.setLastName(vXUser.getLastName());
		if("null".equalsIgnoreCase(vXPortalUser.getLastName())){
			vXPortalUser.setLastName("");
		}
		vXPortalUser.setEmailAddress(vXUser.getEmailAddress());
		if (vXPortalUser.getFirstName() != null
				&& vXPortalUser.getLastName() != null
				&& !vXPortalUser.getFirstName().trim().isEmpty()
				&& !vXPortalUser.getLastName().trim().isEmpty()) {
			vXPortalUser.setPublicScreenName(vXPortalUser.getFirstName() + " "
					+ vXPortalUser.getLastName());
		} else {
			vXPortalUser.setPublicScreenName(vXUser.getName());
		}
		vXPortalUser.setPassword(actualPassword);
		vXPortalUser.setUserRoleList(vXUser.getUserRoleList());
		vXPortalUser = userMgr.createDefaultAccountUser(vXPortalUser);

		VXUser createdXUser = xUserService.createResource(vXUser);

		createdXUser.setPassword(actualPassword);
		List<XXTrxLog> trxLogList = xUserService.getTransactionLog(
				createdXUser, "create");

		String hiddenPassword = PropertiesUtil.getProperty("ranger.password.hidden", "*****");
		createdXUser.setPassword(hiddenPassword);

		Collection<Long> groupIdList = vXUser.getGroupIdList();
		List<VXGroupUser> vXGroupUsers = new ArrayList<VXGroupUser>();
		if (groupIdList != null) {
			for (Long groupId : groupIdList) {
				VXGroupUser vXGroupUser = createXGroupUser(
						createdXUser.getId(), groupId);
				// trxLogList.addAll(xGroupUserService.getTransactionLog(
				// vXGroupUser, "create"));
				vXGroupUsers.add(vXGroupUser);
			}
		}
		for (VXGroupUser vXGroupUser : vXGroupUsers) {
			trxLogList.addAll(xGroupUserService.getTransactionLog(vXGroupUser,
					"create"));
		}
		//
		xaBizUtil.createTrxLog(trxLogList);
		if(vXPortalUser!=null){
			assignPermissionToUser(vXPortalUser, true);
		}

		return createdXUser;
	}

	public void assignPermissionToUser(VXPortalUser vXPortalUser, boolean isCreate) {
		HashMap<String, Long> moduleNameId = getAllModuleNameAndIdMap();
		if(moduleNameId!=null && vXPortalUser!=null){
			if(CollectionUtils.isNotEmpty(vXPortalUser.getUserRoleList())){
				for (String role : vXPortalUser.getUserRoleList()) {

					if (role.equals(RangerConstants.ROLE_USER)) {

						createOrUpdateUserPermisson(vXPortalUser, moduleNameId.get(RangerConstants.MODULE_RESOURCE_BASED_POLICIES), isCreate);
						createOrUpdateUserPermisson(vXPortalUser, moduleNameId.get(RangerConstants.MODULE_REPORTS), isCreate);
					} else if (role.equals(RangerConstants.ROLE_SYS_ADMIN)) {

						createOrUpdateUserPermisson(vXPortalUser, moduleNameId.get(RangerConstants.MODULE_REPORTS), isCreate);
						createOrUpdateUserPermisson(vXPortalUser, moduleNameId.get(RangerConstants.MODULE_RESOURCE_BASED_POLICIES), isCreate);
						createOrUpdateUserPermisson(vXPortalUser, moduleNameId.get(RangerConstants.MODULE_AUDIT), isCreate);
						createOrUpdateUserPermisson(vXPortalUser, moduleNameId.get(RangerConstants.MODULE_USER_GROUPS), isCreate);
						createOrUpdateUserPermisson(vXPortalUser, moduleNameId.get(RangerConstants.MODULE_TAG_BASED_POLICIES), isCreate);
					} else if (role.equals(RangerConstants.ROLE_KEY_ADMIN)) {

						createOrUpdateUserPermisson(vXPortalUser, moduleNameId.get(RangerConstants.MODULE_KEY_MANAGER), isCreate);
						createOrUpdateUserPermisson(vXPortalUser, moduleNameId.get(RangerConstants.MODULE_REPORTS), isCreate);
						createOrUpdateUserPermisson(vXPortalUser, moduleNameId.get(RangerConstants.MODULE_RESOURCE_BASED_POLICIES), isCreate);
					}

				}
			}
		}
	}

	// Insert or Updating Mapping permissions depending upon roles
	public void createOrUpdateUserPermisson(VXPortalUser portalUser, Long moduleId, boolean isCreate) {
		VXUserPermission vXUserPermission;
		XXUserPermission xUserPermission = daoManager.getXXUserPermission().findByModuleIdAndPortalUserId(portalUser.getId(), moduleId);
		if (xUserPermission == null) {
			vXUserPermission = new VXUserPermission();

			// When Creating XXUserPermission UI sends xUserId, to keep it consistent here xUserId should be used
			XXUser xUser = daoManager.getXXUser().findByPortalUserId(portalUser.getId());
			if (xUser == null) {
				logger.warn("Could not found corresponding xUser for username: [" + portalUser.getLoginId() + "], So not assigning permission to this user");
				return;
			} else {
				vXUserPermission.setUserId(xUser.getId());
			}

			vXUserPermission.setIsAllowed(RangerCommonEnums.IS_ALLOWED);
			vXUserPermission.setModuleId(moduleId);
			try {
				vXUserPermission = this.createXUserPermission(vXUserPermission);
				logger.info("Permission assigned to user: [" + vXUserPermission.getUserName() + "] For Module: [" + vXUserPermission.getModuleName() + "]");
			} catch (Exception e) {
				logger.error("Error while assigning permission to user: [" + portalUser.getLoginId() + "] for module: [" + moduleId + "]", e);
			}
		} else if (isCreate) {
			vXUserPermission = xUserPermissionService.populateViewBean(xUserPermission);
			vXUserPermission.setIsAllowed(RangerCommonEnums.IS_ALLOWED);
			vXUserPermission = this.updateXUserPermission(vXUserPermission);
			logger.info("Permission Updated for user: [" + vXUserPermission.getUserName() + "] For Module: [" + vXUserPermission.getModuleName() + "]");
		}
	}

	public HashMap<String, Long> getAllModuleNameAndIdMap() {

		List<XXModuleDef> xXModuleDefs = daoManager.getXXModuleDef().getAll();

		if (!CollectionUtils.isEmpty(xXModuleDefs)) {
			HashMap<String, Long> moduleNameAndIdMap = new HashMap<String, Long>();
			for (XXModuleDef xXModuleDef : xXModuleDefs) {
				moduleNameAndIdMap.put(xXModuleDef.getModule(), xXModuleDef.getId());
			}
			return moduleNameAndIdMap;
		}

		return null;
	}

	private VXGroupUser createXGroupUser(Long userId, Long groupId) {
		VXGroupUser vXGroupUser = new VXGroupUser();
		vXGroupUser.setParentGroupId(groupId);
		vXGroupUser.setUserId(userId);
		VXGroup vXGroup = xGroupService.readResource(groupId);
		vXGroupUser.setName(vXGroup.getName());
		vXGroupUser = xGroupUserService.createResource(vXGroupUser);

		return vXGroupUser;
	}

	public VXUser updateXUser(VXUser vXUser) {
		if (vXUser == null || vXUser.getName() == null
				|| "null".equalsIgnoreCase(vXUser.getName())
				|| vXUser.getName().trim().isEmpty()) {
			throw restErrorUtil.createRESTException("Please provide a valid "
					+ "username.", MessageEnums.INVALID_INPUT_DATA);
		}
		checkAccess(vXUser.getName());
		VXPortalUser oldUserProfile = userMgr.getUserProfileByLoginId(vXUser
				.getName());
		if (oldUserProfile == null) {
			throw restErrorUtil.createRESTException(
					"user " + vXUser.getName() + " does not exist.",
					MessageEnums.INVALID_INPUT_DATA);
		}
		VXPortalUser vXPortalUser = new VXPortalUser();
		if (oldUserProfile != null && oldUserProfile.getId() != null) {
			vXPortalUser.setId(oldUserProfile.getId());
		}

		vXPortalUser.setFirstName(vXUser.getFirstName());
		if("null".equalsIgnoreCase(vXPortalUser.getFirstName())){
			vXPortalUser.setFirstName("");
		}
		vXPortalUser.setLastName(vXUser.getLastName());
		if("null".equalsIgnoreCase(vXPortalUser.getLastName())){
			vXPortalUser.setLastName("");
		}
		vXPortalUser.setEmailAddress(vXUser.getEmailAddress());
		vXPortalUser.setLoginId(vXUser.getName());
		vXPortalUser.setStatus(vXUser.getStatus());
		vXPortalUser.setUserRoleList(vXUser.getUserRoleList());
		if (vXPortalUser.getFirstName() != null
				&& vXPortalUser.getLastName() != null
				&& !vXPortalUser.getFirstName().trim().isEmpty()
				&& !vXPortalUser.getLastName().trim().isEmpty()) {
			vXPortalUser.setPublicScreenName(vXPortalUser.getFirstName() + " "
					+ vXPortalUser.getLastName());
		} else {
			vXPortalUser.setPublicScreenName(vXUser.getName());
		}
		vXPortalUser.setUserSource(vXUser.getUserSource());
		String hiddenPasswordString = PropertiesUtil.getProperty("ranger.password.hidden", "*****");
		String password = vXUser.getPassword();
		if (oldUserProfile != null && password != null
				&& password.equals(hiddenPasswordString)) {
			vXPortalUser.setPassword(oldUserProfile.getPassword());
		}
                else if(oldUserProfile != null && oldUserProfile.getUserSource() == RangerCommonEnums.USER_EXTERNAL && password != null){
                        vXPortalUser.setPassword(oldUserProfile.getPassword());
                        logger.debug("User is trrying to change external user password which we are not allowing it to change");
                }
        else if(password != null){
                validatePassword(vXUser);
                vXPortalUser.setPassword(password);
        }
		Collection<Long> groupIdList = vXUser.getGroupIdList();
		XXPortalUser xXPortalUser = new XXPortalUser();
		xXPortalUser = userMgr.updateUserWithPass(vXPortalUser);
		//update permissions start
		Collection<String> roleListUpdatedProfile =new ArrayList<String>();
		if (oldUserProfile != null && oldUserProfile.getId() != null) {
			if(vXUser!=null && vXUser.getUserRoleList()!=null){
				Collection<String> roleListOldProfile = oldUserProfile.getUserRoleList();
				Collection<String> roleListNewProfile = vXUser.getUserRoleList();
				if(roleListNewProfile!=null && roleListOldProfile!=null){
					for (String role : roleListNewProfile) {
						if(role!=null && !roleListOldProfile.contains(role)){
							roleListUpdatedProfile.add(role);
						}
					}
					
				}
			}
		}
		if(roleListUpdatedProfile!=null && roleListUpdatedProfile.size()>0){
			vXPortalUser.setUserRoleList(roleListUpdatedProfile);
			List<XXUserPermission> xuserPermissionList = daoManager
					.getXXUserPermission()
					.findByUserPermissionId(vXPortalUser.getId());
			if (xuserPermissionList!=null && xuserPermissionList.size()>0){
				for (XXUserPermission xXUserPermission : xuserPermissionList) {
					if (xXUserPermission != null) {
						try {
							xUserPermissionService.deleteResource(xXUserPermission.getId());
						} catch (Exception e) {
							logger.error(e.getMessage());
						}
					}
				}
			}
			assignPermissionToUser(vXPortalUser,true);
		}
		//update permissions end
		Collection<String> roleList = new ArrayList<String>();
		if (xXPortalUser != null) {
			roleList = userMgr.getRolesForUser(xXPortalUser);
		}
		if (roleList == null || roleList.size() == 0) {
			roleList = new ArrayList<String>();
			roleList.add(RangerConstants.ROLE_USER);
		}

		// TODO I've to get the transaction log from here.
		// There is nothing to log anything in XXUser so far.
		vXUser = xUserService.updateResource(vXUser);
		vXUser.setUserRoleList(roleList);
        if (oldUserProfile.getUserSource() == RangerCommonEnums.USER_APP) {
		vXUser.setPassword(password);
        }
        else if (oldUserProfile.getUserSource() == RangerCommonEnums.USER_EXTERNAL) {
            vXUser.setPassword(oldUserProfile.getPassword());
        }

		List<XXTrxLog> trxLogList = xUserService.getTransactionLog(vXUser,
				oldUserProfile, "update");
		vXUser.setPassword(hiddenPasswordString);

		Long userId = vXUser.getId();
		List<Long> groupUsersToRemove = new ArrayList<Long>();

		if (groupIdList != null) {
			SearchCriteria searchCriteria = new SearchCriteria();
			searchCriteria.addParam("xUserId", userId);
			VXGroupUserList vXGroupUserList = xGroupUserService
					.searchXGroupUsers(searchCriteria);
			List<VXGroupUser> vXGroupUsers = vXGroupUserList.getList();

			if (vXGroupUsers != null) {

				// Create
				for (Long groupId : groupIdList) {
					boolean found = false;
					for (VXGroupUser vXGroupUser : vXGroupUsers) {
						if (groupId.equals(vXGroupUser.getParentGroupId())) {
							found = true;
							break;
						}
					}
					if (!found) {
						VXGroupUser vXGroupUser = createXGroupUser(userId,
								groupId);
						trxLogList.addAll(xGroupUserService.getTransactionLog(
								vXGroupUser, "create"));
					}
				}

				// Delete
				for (VXGroupUser vXGroupUser : vXGroupUsers) {
					boolean found = false;
					for (Long groupId : groupIdList) {
						if (groupId.equals(vXGroupUser.getParentGroupId())) {
							trxLogList.addAll(xGroupUserService
									.getTransactionLog(vXGroupUser, "update"));
							found = true;
							break;
						}
					}
					if (!found) {
						// TODO I've to get the transaction log from here.
						trxLogList.addAll(xGroupUserService.getTransactionLog(
								vXGroupUser, "delete"));
						groupUsersToRemove.add(vXGroupUser.getId());
						// xGroupUserService.deleteResource(vXGroupUser.getId());
					}
				}

			} else {
				for (Long groupId : groupIdList) {
					VXGroupUser vXGroupUser = createXGroupUser(userId, groupId);
					trxLogList.addAll(xGroupUserService.getTransactionLog(
							vXGroupUser, "create"));
				}
			}
			vXUser.setGroupIdList(groupIdList);
		} else {
			logger.debug("Group id list can't be null for user. Group user "
					+ "mapping not updated for user : " + userId);
		}

		xaBizUtil.createTrxLog(trxLogList);

		for (Long groupUserId : groupUsersToRemove) {
			xGroupUserService.deleteResource(groupUserId);
		}

		return vXUser;
	}

	public VXUserGroupInfo createXUserGroupFromMap(
			VXUserGroupInfo vXUserGroupInfo) {
		checkAdminAccess();
		VXUserGroupInfo vxUGInfo = new VXUserGroupInfo();

		VXUser vXUser = vXUserGroupInfo.getXuserInfo();
                VXPortalUser vXPortalUser = userMgr.getUserProfileByLoginId(vXUser.getName());
            XXPortalUser xxPortalUser = daoManager.getXXPortalUser().findByLoginId(vXUser.getName());
            Collection<String> reqRoleList = vXUser.getUserRoleList();
            List<String> existingRole = daoManager.getXXPortalUserRole().findXPortalUserRolebyXPortalUserId(xxPortalUser.getId());
            if (xxPortalUser.getUserSource() == RangerCommonEnums.USER_EXTERNAL) {
                vXPortalUser = userManager.updateRoleForExternalUsers(reqRoleList,existingRole, vXPortalUser);
            }
		vXUser = xUserService.createXUserWithOutLogin(vXUser);

		vxUGInfo.setXuserInfo(vXUser);

		List<VXGroup> vxg = new ArrayList<VXGroup>();

		for (VXGroup vXGroup : vXUserGroupInfo.getXgroupInfo()) {
			VXGroup VvXGroup = xGroupService.createXGroupWithOutLogin(vXGroup);
			vxg.add(VvXGroup);
			VXGroupUser vXGroupUser = new VXGroupUser();
			vXGroupUser.setUserId(vXUser.getId());
			vXGroupUser.setName(VvXGroup.getName());
			vXGroupUser = xGroupUserService
					.createXGroupUserWithOutLogin(vXGroupUser);
		}
                if (vXPortalUser != null) {
			assignPermissionToUser(vXPortalUser, true);
		}
		vxUGInfo.setXgroupInfo(vxg);

		return vxUGInfo;
	}
	
	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public VXGroupUserInfo createXGroupUserFromMap(
			VXGroupUserInfo vXGroupUserInfo) {
		checkAdminAccess();
		VXGroupUserInfo vxGUInfo = new VXGroupUserInfo();

		VXGroup vXGroup = vXGroupUserInfo.getXgroupInfo();
		// Add the group user mappings for a given group to x_group_user table
		/*XXGroup xGroup = daoManager.getXXGroup().findByGroupName(vXGroup.getName());
		if (xGroup == null) {
			return vxGUInfo;
		}*/

		List<VXUser> vxu = new ArrayList<VXUser>();

		for (VXUser vXUser : vXGroupUserInfo.getXuserInfo()) {
                        XXUser xUser = daoManager.getXXUser().findByUserName(
                                        vXUser.getName());
                        XXPortalUser xXPortalUser = daoManager.getXXPortalUser()
                                        .findByLoginId(vXUser.getName());
			if (xUser != null) {
                                // Add or update group user mapping only if the user already
                                // exists in x_user table.
				logger.debug(String.format("createXGroupUserFromMap(): Create or update group %s ", vXGroup.getName()));
				vXGroup = xGroupService.createXGroupWithOutLogin(vXGroup);
				vxGUInfo.setXgroupInfo(vXGroup);
				vxu.add(vXUser);
				VXGroupUser vXGroupUser = new VXGroupUser();
				vXGroupUser.setUserId(xUser.getId());
				vXGroupUser.setName(vXGroup.getName());
                                if (xXPortalUser.getUserSource() == RangerCommonEnums.USER_EXTERNAL) {
                                        vXGroupUser = xGroupUserService
                                                        .createXGroupUserWithOutLogin(vXGroupUser);
									logger.debug(String.format("createXGroupUserFromMap(): Create or update group user mapping with groupname =  " + vXGroup.getName()
											+ " username = %s userId = %d", xXPortalUser.getLoginId(), xUser.getId()));
                                }
                                Collection<String> reqRoleList = vXUser.getUserRoleList();

                                XXPortalUser xxPortalUser = daoManager.getXXPortalUser()
                                                .findByLoginId(vXUser.getName());
                                List<String> existingRole = daoManager.getXXPortalUserRole()
                                                .findXPortalUserRolebyXPortalUserId(
                                                                xxPortalUser.getId());
                                VXPortalUser vxPortalUser = userManager
                                                .mapXXPortalUserToVXPortalUserForDefaultAccount(xxPortalUser);
                                if (xxPortalUser.getUserSource() == RangerCommonEnums.USER_EXTERNAL) {
                                        vxPortalUser = userManager.updateRoleForExternalUsers(
                                                        reqRoleList, existingRole, vxPortalUser);
                                        assignPermissionToUser(vxPortalUser, true);
                                }
			}
		}

		vxGUInfo.setXuserInfo(vxu);

		return vxGUInfo;
	}
	
	public VXGroupUserInfo getXGroupUserFromMap(
			String groupName) {
		checkAdminAccess();
		VXGroupUserInfo vxGUInfo = new VXGroupUserInfo();

		XXGroup xGroup = daoManager.getXXGroup().findByGroupName(groupName);
		if (xGroup == null) {
			return vxGUInfo;
		}

		VXGroup xgroupInfo = xGroupService.populateViewBean(xGroup);
		vxGUInfo.setXgroupInfo(xgroupInfo);

		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addParam("xGroupId", xGroup.getId());

		VXGroupUserList vxGroupUserList = searchXGroupUsers(searchCriteria);
		List<VXUser> vxu = new ArrayList<VXUser>();
		logger.debug("removing all the group user mapping for : " + xGroup.getName());
		for (VXGroupUser groupUser : vxGroupUserList.getList()) {
			XXUser xUser = daoManager.getXXUser().getById(groupUser.getUserId());
			if (xUser != null) {
				VXUser vxUser = new VXUser();
				vxUser.setName(xUser.getName());
				vxu.add(vxUser);
			}
			
		}
		vxGUInfo.setXuserInfo(vxu);

		return vxGUInfo;
	}


	public VXUser createXUserWithOutLogin(VXUser vXUser) {
		checkAdminAccess();
                validatePassword(vXUser);
		return xUserService.createXUserWithOutLogin(vXUser);
	}

	public VXGroup createXGroup(VXGroup vXGroup) {
		checkAdminAccess();
		if (vXGroup.getDescription() == null) {
			vXGroup.setDescription(vXGroup.getName());
		}

		vXGroup = xGroupService.createResource(vXGroup);
		List<XXTrxLog> trxLogList = xGroupService.getTransactionLog(vXGroup,
				"create");
		xaBizUtil.createTrxLog(trxLogList);
		return vXGroup;
	}

	public VXGroup createXGroupWithoutLogin(VXGroup vXGroup) {
		checkAdminAccess();
		return xGroupService.createXGroupWithOutLogin(vXGroup);
	}

	public VXGroupUser createXGroupUser(VXGroupUser vXGroupUser) {
		checkAdminAccess();
		vXGroupUser = xGroupUserService
				.createXGroupUserWithOutLogin(vXGroupUser);
		return vXGroupUser;
	}

	public VXUser getXUser(Long id) {
		VXUser vXUser=null;
		vXUser=xUserService.readResourceWithOutLogin(id);
                if(vXUser != null){
                        if(!hasAccessToGetUserInfo(vXUser)){
                                logger.info("Logged-In user is not allowed to access requested user data.");
                                throw restErrorUtil.create403RESTException("Logged-In user is not allowed to access requested user data.");
                                }
                }
		if(vXUser!=null && !hasAccessToModule(RangerConstants.MODULE_USER_GROUPS)){
			vXUser=getMaskedVXUser(vXUser);
		}
		return vXUser;
	}

	public VXGroupUser getXGroupUser(Long id) {
		return xGroupUserService.readResourceWithOutLogin(id);

	}

	public VXGroup getXGroup(Long id) {
		VXGroup vXGroup=null;
                        UserSessionBase userSession = ContextUtil.getCurrentUserSession();
                        if (userSession != null && userSession.getLoginId() != null) {
                                        VXUser loggedInVXUser = xUserService.getXUserByUserName(userSession
                                                        .getLoginId());
                                        if (loggedInVXUser != null) {
                                                if (loggedInVXUser.getUserRoleList().size() == 1
                                                                && loggedInVXUser.getUserRoleList().contains(
                                                                                RangerConstants.ROLE_USER)) {

                                                        List<Long> listGroupId = daoManager.getXXGroupUser()
                                                                        .findGroupIdListByUserId(loggedInVXUser.getId());

                                                        if (!listGroupId.contains(id)) {
                                                                logger.info("Logged-In user is not allowed to access requested user data.");
                                                                throw restErrorUtil
                                                                                .create403RESTException("Logged-In user is not allowed to access requested group data.");
                                                        }

                                                }
                                        }
                        }
		vXGroup=xGroupService.readResourceWithOutLogin(id);
		if(vXGroup!=null && !hasAccessToModule(RangerConstants.MODULE_USER_GROUPS)){
			vXGroup=getMaskedVXGroup(vXGroup);
		}
		return vXGroup;
	}

	/**
	 * // public void createXGroupAndXUser(String groupName, String userName) {
	 *
	 * // Long groupId; // Long userId; // XXGroup xxGroup = //
	 * appDaoManager.getXXGroup().findByGroupName(groupName); // VXGroup
	 * vxGroup; // if (xxGroup == null) { // vxGroup = new VXGroup(); //
	 * vxGroup.setName(groupName); // vxGroup.setDescription(groupName); //
	 * vxGroup.setGroupType(AppConstants.XA_GROUP_USER); //
	 * vxGroup.setPriAcctId(1l); // vxGroup.setPriGrpId(1l); // vxGroup =
	 * xGroupService.createResource(vxGroup); // groupId = vxGroup.getId(); // }
	 * else { // groupId = xxGroup.getId(); // } // XXUser xxUser =
	 * appDaoManager.getXXUser().findByUserName(userName); // VXUser vxUser; //
	 * if (xxUser == null) { // vxUser = new VXUser(); //
	 * vxUser.setName(userName); // vxUser.setDescription(userName); //
	 * vxUser.setPriGrpId(1l); // vxUser.setPriAcctId(1l); // vxUser =
	 * xUserService.createResource(vxUser); // userId = vxUser.getId(); // }
	 * else { // userId = xxUser.getId(); // } // VXGroupUser vxGroupUser = new
	 * VXGroupUser(); // vxGroupUser.setParentGroupId(groupId); //
	 * vxGroupUser.setUserId(userId); // vxGroupUser.setName(groupName); //
	 * vxGroupUser.setPriAcctId(1l); // vxGroupUser.setPriGrpId(1l); //
	 * vxGroupUser = xGroupUserService.createResource(vxGroupUser);
	 *
	 * // }
	 */

	public void deleteXGroupAndXUser(String groupName, String userName) {
		checkAdminAccess();
		VXGroup vxGroup = xGroupService.getGroupByGroupName(groupName);
		VXUser vxUser = xUserService.getXUserByUserName(userName);
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addParam("xGroupId", vxGroup.getId());
		searchCriteria.addParam("xUserId", vxUser.getId());
		VXGroupUserList vxGroupUserList = xGroupUserService
				.searchXGroupUsers(searchCriteria);
		for (VXGroupUser vxGroupUser : vxGroupUserList.getList()) {
			daoManager.getXXGroupUser().remove(vxGroupUser.getId());
		}
	}

	public VXGroupList getXUserGroups(Long xUserId) {
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addParam("xUserId", xUserId);
		VXGroupUserList vXGroupUserList = xGroupUserService
				.searchXGroupUsers(searchCriteria);
		VXGroupList vXGroupList = new VXGroupList();
		List<VXGroup> vXGroups = new ArrayList<VXGroup>();
		if (vXGroupUserList != null) {
			List<VXGroupUser> vXGroupUsers = vXGroupUserList.getList();
			Set<Long> groupIdList = new HashSet<Long>();
			for (VXGroupUser vXGroupUser : vXGroupUsers) {
				groupIdList.add(vXGroupUser.getParentGroupId());
			}
			for (Long groupId : groupIdList) {
				VXGroup vXGroup = xGroupService.readResource(groupId);
				vXGroups.add(vXGroup);
			}
			vXGroupList.setVXGroups(vXGroups);
		} else {
			logger.debug("No groups found for user id : " + xUserId);
		}
		return vXGroupList;
	}

	public Set<String> getGroupsForUser(String userName) {
		Set<String> ret = new HashSet<String>();

		try {
			VXUser user = getXUserByUserName(userName);

			if (user != null) {
				VXGroupList groups = getXUserGroups(user.getId());

				if (groups != null
						&& !CollectionUtils.isEmpty(groups.getList())) {
					for (VXGroup group : groups.getList()) {
						ret.add(group.getName());
					}
				} else {
					if (logger.isDebugEnabled()) {
						logger.debug("getGroupsForUser('" + userName
								+ "'): no groups found for user");
					}
				}
			} else {
				if (logger.isDebugEnabled()) {
					logger.debug("getGroupsForUser('" + userName
							+ "'): user not found");
				}
			}
		} catch (Exception excp) {
			logger.error("getGroupsForUser('" + userName + "') failed", excp);
		}

		return ret;
	}

	public VXUserList getXGroupUsers(Long xGroupId) {
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addParam("xGroupId", xGroupId);
		VXGroupUserList vXGroupUserList = xGroupUserService
				.searchXGroupUsers(searchCriteria);
		VXUserList vXUserList = new VXUserList();

		List<VXUser> vXUsers = new ArrayList<VXUser>();
		if (vXGroupUserList != null) {
			List<VXGroupUser> vXGroupUsers = vXGroupUserList.getList();
			Set<Long> userIdList = new HashSet<Long>();
			for (VXGroupUser vXGroupUser : vXGroupUsers) {
				userIdList.add(vXGroupUser.getUserId());
			}
			for (Long userId : userIdList) {
				VXUser vXUser = xUserService.readResource(userId);
				vXUsers.add(vXUser);

			}
			vXUserList.setVXUsers(vXUsers);
		} else {
			logger.debug("No users found for group id : " + xGroupId);
		}
		return vXUserList;
	}

	// FIXME Hack : Unnecessary, to be removed after discussion.
	private void setUserDesc(VXUser vXUser) {
		vXUser.setDescription(vXUser.getName());
	}

	@Override
	public VXGroup updateXGroup(VXGroup vXGroup) {
		checkAdminAccess();
		XXGroup xGroup = daoManager.getXXGroup().getById(vXGroup.getId());
		if (vXGroup != null && xGroup != null && !vXGroup.getName().equals(xGroup.getName())) {
			throw restErrorUtil.createRESTException(
					"group name updates are not allowed.",
					MessageEnums.INVALID_INPUT_DATA);
		}
		List<XXTrxLog> trxLogList = xGroupService.getTransactionLog(vXGroup,
				xGroup, "update");
		xaBizUtil.createTrxLog(trxLogList);
		vXGroup = (VXGroup) xGroupService.updateResource(vXGroup);
		if (vXGroup != null) {
			updateXgroupUserForGroupUpdate(vXGroup);
			RangerServicePoliciesCache.sInstance=null;
		}
		return vXGroup;
	}

	private void updateXgroupUserForGroupUpdate(VXGroup vXGroup) {
		List<XXGroupUser> grpUsers = daoManager.getXXGroupUser().findByGroupId(vXGroup.getId());
		if(CollectionUtils.isNotEmpty(grpUsers)){
			for (XXGroupUser grpUser : grpUsers) {
				VXGroupUser vXGroupUser = xGroupUserService.populateViewBean(grpUser);
				vXGroupUser.setName(vXGroup.getName());
				updateXGroupUser(vXGroupUser);
			}
		}
	}

	public VXGroupUser updateXGroupUser(VXGroupUser vXGroupUser) {
		checkAdminAccess();
		return super.updateXGroupUser(vXGroupUser);
	}

	public void deleteXGroupUser(Long id, boolean force) {
		checkAdminAccess();
		super.deleteXGroupUser(id, force);
	}

	public VXGroupGroup createXGroupGroup(VXGroupGroup vXGroupGroup){
		checkAdminAccess();
		return super.createXGroupGroup(vXGroupGroup);
	}

	public VXGroupGroup updateXGroupGroup(VXGroupGroup vXGroupGroup) {
		checkAdminAccess();
		return super.updateXGroupGroup(vXGroupGroup);
	}

	public void deleteXGroupGroup(Long id, boolean force) {
		checkAdminAccess();
		super.deleteXGroupGroup(id, force);
	}

	public void deleteXPermMap(Long id, boolean force) {
		if (force) {
			XXPermMap xPermMap = daoManager.getXXPermMap().getById(id);
			if (xPermMap != null) {
				if (xResourceService.readResource(xPermMap.getResourceId()) == null) {
					throw restErrorUtil.createRESTException("Invalid Input Data - No resource found with Id: " + xPermMap.getResourceId(), MessageEnums.INVALID_INPUT_DATA);
				}
			}

			xPermMapService.deleteResource(id);
		} else {
			throw restErrorUtil.createRESTException("serverMsg.modelMgrBaseDeleteModel", MessageEnums.OPER_NOT_ALLOWED_FOR_ENTITY);
		}
	}

	public VXLong getXPermMapSearchCount(SearchCriteria searchCriteria) {
		VXPermMapList permMapList = xPermMapService.searchXPermMaps(searchCriteria);
		VXLong vXLong = new VXLong();
		vXLong.setValue(permMapList.getListSize());
		return vXLong;
	}

	public void deleteXAuditMap(Long id, boolean force) {
		if (force) {
			XXAuditMap xAuditMap = daoManager.getXXAuditMap().getById(id);
			if (xAuditMap != null) {
				if (xResourceService.readResource(xAuditMap.getResourceId()) == null) {
					throw restErrorUtil.createRESTException("Invalid Input Data - No resource found with Id: " + xAuditMap.getResourceId(), MessageEnums.INVALID_INPUT_DATA);
				}
			}

			xAuditMapService.deleteResource(id);
		} else {
			throw restErrorUtil.createRESTException("serverMsg.modelMgrBaseDeleteModel", MessageEnums.OPER_NOT_ALLOWED_FOR_ENTITY);
		}
	}

	public VXLong getXAuditMapSearchCount(SearchCriteria searchCriteria) {
		VXAuditMapList auditMapList = xAuditMapService.searchXAuditMaps(searchCriteria);
		VXLong vXLong = new VXLong();
		vXLong.setValue(auditMapList.getListSize());
		return vXLong;
	}

	public void modifyUserVisibility(HashMap<Long, Integer> visibilityMap) {
		checkAdminAccess();
		Set<Map.Entry<Long, Integer>> entries = visibilityMap.entrySet();
		for (Map.Entry<Long, Integer> entry : entries) {
			XXUser xUser = daoManager.getXXUser().getById(entry.getKey());
			VXUser vObj = xUserService.populateViewBean(xUser);
			vObj.setIsVisible(entry.getValue());
			vObj = xUserService.updateResource(vObj);
		}
	}

	public void modifyGroupsVisibility(HashMap<Long, Integer> groupVisibilityMap) {
		checkAdminAccess();
		Set<Map.Entry<Long, Integer>> entries = groupVisibilityMap.entrySet();
		for (Map.Entry<Long, Integer> entry : entries) {
			XXGroup xGroup = daoManager.getXXGroup().getById(entry.getKey());
			VXGroup vObj = xGroupService.populateViewBean(xGroup);
			vObj.setIsVisible(entry.getValue());
			vObj = xGroupService.updateResource(vObj);
		}
	}

	// Module permissions
	public VXModuleDef createXModuleDefPermission(VXModuleDef vXModuleDef) {

		XXModuleDef xModDef = daoManager.getXXModuleDef().findByModuleName(vXModuleDef.getModule());

		if (xModDef != null) {
			throw restErrorUtil.createRESTException("Module Def with same name already exists.", MessageEnums.ERROR_DUPLICATE_OBJECT);
		}

		return xModuleDefService.createResource(vXModuleDef);
	}

	public VXModuleDef getXModuleDefPermission(Long id) {
		return xModuleDefService.readResource(id);
	}

	public VXModuleDef updateXModuleDefPermission(VXModuleDef vXModuleDef) {

		List<VXGroupPermission> groupPermListNew = vXModuleDef.getGroupPermList();
		List<VXUserPermission> userPermListNew = vXModuleDef.getUserPermList();

		List<VXGroupPermission> groupPermListOld = new ArrayList<VXGroupPermission>();
		List<VXUserPermission> userPermListOld = new ArrayList<VXUserPermission>();

		XXModuleDef xModuleDef = daoManager.getXXModuleDef().getById(vXModuleDef.getId());
		VXModuleDef vModuleDefPopulateOld = xModuleDefService.populateViewBean(xModuleDef);

		List<XXGroupPermission> xgroupPermissionList = daoManager.getXXGroupPermission().findByModuleId(vXModuleDef.getId(), true);
                Map<Long, XXGroup> xXGroupMap=xGroupService.getXXGroupIdXXGroupMap();
                if(xXGroupMap==null || xXGroupMap.isEmpty()){
                        for (XXGroupPermission xGrpPerm : xgroupPermissionList) {
                                VXGroupPermission vXGrpPerm = xGroupPermissionService.populateViewBean(xGrpPerm);
                                groupPermListOld.add(vXGrpPerm);
                        }
                }else{
                        groupPermListOld=xGroupPermissionService.getPopulatedVXGroupPermissionList(xgroupPermissionList,xXGroupMap,vModuleDefPopulateOld);
		}
		vModuleDefPopulateOld.setGroupPermList(groupPermListOld);

		List<XXUserPermission> xuserPermissionList = daoManager.getXXUserPermission().findByModuleId(vXModuleDef.getId(), true);
                Map<Long, XXUser> xXPortalUserIdXXUserMap=xUserService.getXXPortalUserIdXXUserMap();
                if(xXPortalUserIdXXUserMap==null || xXPortalUserIdXXUserMap.isEmpty()){
                        for (XXUserPermission xUserPerm : xuserPermissionList) {
                                VXUserPermission vUserPerm = xUserPermissionService.populateViewBean(xUserPerm);
                                userPermListOld.add(vUserPerm);
                        }
                }else{
                        userPermListOld=xUserPermissionService.getPopulatedVXUserPermissionList(xuserPermissionList,xXPortalUserIdXXUserMap,vModuleDefPopulateOld);
		}
		vModuleDefPopulateOld.setUserPermList(userPermListOld);

		if (groupPermListOld != null && groupPermListNew != null) {
			for (VXGroupPermission newVXGroupPerm : groupPermListNew) {

				boolean isExist = false;

				for (VXGroupPermission oldVXGroupPerm : groupPermListOld) {
					if (newVXGroupPerm.getModuleId().equals(oldVXGroupPerm.getModuleId()) && newVXGroupPerm.getGroupId().equals(oldVXGroupPerm.getGroupId())) {
						if (!newVXGroupPerm.getIsAllowed().equals(oldVXGroupPerm.getIsAllowed())) {
							oldVXGroupPerm.setIsAllowed(newVXGroupPerm.getIsAllowed());
							oldVXGroupPerm = this.updateXGroupPermission(oldVXGroupPerm);
						}
						isExist = true;
					}
				}
				if (!isExist) {
					newVXGroupPerm = this.createXGroupPermission(newVXGroupPerm);
				}
			}
		}

		if (userPermListOld != null && userPermListNew != null) {
			for (VXUserPermission newVXUserPerm : userPermListNew) {

				boolean isExist = false;
				for (VXUserPermission oldVXUserPerm : userPermListOld) {
					if (newVXUserPerm.getModuleId().equals(oldVXUserPerm.getModuleId()) && newVXUserPerm.getUserId().equals(oldVXUserPerm.getUserId())) {
						if (!newVXUserPerm.getIsAllowed().equals(oldVXUserPerm.getIsAllowed())) {
							oldVXUserPerm.setIsAllowed(newVXUserPerm.getIsAllowed());
							oldVXUserPerm = this.updateXUserPermission(oldVXUserPerm);
						}
						isExist = true;
					}
				}
				if (!isExist) {
					newVXUserPerm = this.createXUserPermission(newVXUserPerm);
				}
			}
		}
		vXModuleDef = xModuleDefService.updateResource(vXModuleDef);

		return vXModuleDef;
	}

	public void deleteXModuleDefPermission(Long id, boolean force) {
		daoManager.getXXUserPermission().deleteByModuleId(id);
		daoManager.getXXGroupPermission().deleteByModuleId(id);
		xModuleDefService.deleteResource(id);
	}

	// User permission
	public VXUserPermission createXUserPermission(VXUserPermission vXUserPermission) {

		vXUserPermission = xUserPermissionService.createResource(vXUserPermission);

		Set<UserSessionBase> userSessions = sessionMgr.getActiveUserSessionsForPortalUserId(vXUserPermission.getUserId());
		if (!CollectionUtils.isEmpty(userSessions)) {
			for (UserSessionBase userSession : userSessions) {
				logger.info("Assigning permission to user who's found logged in into system, so updating permission in session of that user: [" + vXUserPermission.getUserName()
						+ "]");
				sessionMgr.resetUserModulePermission(userSession);
			}
		}

		return vXUserPermission;
	}

	public VXUserPermission getXUserPermission(Long id) {
		return xUserPermissionService.readResource(id);
	}

	public VXUserPermission updateXUserPermission(VXUserPermission vXUserPermission) {

		vXUserPermission = xUserPermissionService.updateResource(vXUserPermission);

		Set<UserSessionBase> userSessions = sessionMgr.getActiveUserSessionsForPortalUserId(vXUserPermission.getUserId());
		if (!CollectionUtils.isEmpty(userSessions)) {
			for (UserSessionBase userSession : userSessions) {
				logger.info("Updating permission of user who's found logged in into system, so updating permission in session of user: [" + vXUserPermission.getUserName() + "]");
				sessionMgr.resetUserModulePermission(userSession);
			}
		}

		return vXUserPermission;
	}

	public void deleteXUserPermission(Long id, boolean force) {

		XXUserPermission xUserPermission = daoManager.getXXUserPermission().getById(id);
		if (xUserPermission == null) {
			throw restErrorUtil.createRESTException("No UserPermission found to delete, ID: " + id, MessageEnums.DATA_NOT_FOUND);
		}

		xUserPermissionService.deleteResource(id);

		Set<UserSessionBase> userSessions = sessionMgr.getActiveUserSessionsForPortalUserId(xUserPermission.getUserId());
		if (!CollectionUtils.isEmpty(userSessions)) {
			for (UserSessionBase userSession : userSessions) {
				logger.info("deleting permission of user who's found logged in into system, so updating permission in session of that user");
				sessionMgr.resetUserModulePermission(userSession);
			}
		}
	}

	// Group permission
	public VXGroupPermission createXGroupPermission(VXGroupPermission vXGroupPermission) {

		vXGroupPermission = xGroupPermissionService.createResource(vXGroupPermission);

		List<XXGroupUser> grpUsers = daoManager.getXXGroupUser().findByGroupId(vXGroupPermission.getGroupId());
		for (XXGroupUser xGrpUser : grpUsers) {
			Set<UserSessionBase> userSessions = sessionMgr.getActiveUserSessionsForXUserId(xGrpUser.getUserId());
			if (!CollectionUtils.isEmpty(userSessions)) {
				for (UserSessionBase userSession : userSessions) {
					logger.info("Assigning permission to group, one of the user belongs to that group found logged in into system, so updating permission in session of that user");
					sessionMgr.resetUserModulePermission(userSession);
				}
			}
		}

		return vXGroupPermission;
	}

	public VXGroupPermission getXGroupPermission(Long id) {
		return xGroupPermissionService.readResource(id);
	}

	public VXGroupPermission updateXGroupPermission(VXGroupPermission vXGroupPermission) {

		vXGroupPermission = xGroupPermissionService.updateResource(vXGroupPermission);

		List<XXGroupUser> grpUsers = daoManager.getXXGroupUser().findByGroupId(vXGroupPermission.getGroupId());
		for (XXGroupUser xGrpUser : grpUsers) {
			Set<UserSessionBase> userSessions = sessionMgr.getActiveUserSessionsForXUserId(xGrpUser.getUserId());
			if (!CollectionUtils.isEmpty(userSessions)) {
				for (UserSessionBase userSession : userSessions) {
					logger.info("Assigning permission to group whose one of the user found logged in into system, so updating permission in session of that user");
					sessionMgr.resetUserModulePermission(userSession);
				}
			}
		}

		return vXGroupPermission;
	}

	public void deleteXGroupPermission(Long id, boolean force) {

		XXGroupPermission xGrpPerm = daoManager.getXXGroupPermission().getById(id);

		if (xGrpPerm == null) {
			throw restErrorUtil.createRESTException("No GroupPermission object with ID: [" + id + "found.", MessageEnums.DATA_NOT_FOUND);
		}

		xGroupPermissionService.deleteResource(id);

		List<XXGroupUser> grpUsers = daoManager.getXXGroupUser().findByGroupId(xGrpPerm.getGroupId());
		for (XXGroupUser xGrpUser : grpUsers) {
			Set<UserSessionBase> userSessions = sessionMgr.getActiveUserSessionsForXUserId(xGrpUser.getUserId());
			if (!CollectionUtils.isEmpty(userSessions)) {
				for (UserSessionBase userSession : userSessions) {
					logger.info("deleting permission of the group whose one of the user found logged in into system, so updating permission in session of that user");
					sessionMgr.resetUserModulePermission(userSession);
				}
			}
		}
	}

	public void modifyUserActiveStatus(HashMap<Long, Integer> statusMap) {
		checkAdminAccess();
		UserSessionBase session = ContextUtil.getCurrentUserSession();
		String currentUser=null;
		if(session!=null){
			currentUser=session.getLoginId();
			if(currentUser==null || currentUser.trim().isEmpty()){
				currentUser=null;
			}
		}
		if(currentUser==null){
			return;
		}
		Set<Map.Entry<Long, Integer>> entries = statusMap.entrySet();
		for (Map.Entry<Long, Integer> entry : entries) {
			if(entry!=null && entry.getKey()!=null && entry.getValue()!=null){
				XXUser xUser = daoManager.getXXUser().getById(entry.getKey());
				if(xUser!=null){
					VXPortalUser vXPortalUser = userMgr.getUserProfileByLoginId(xUser.getName());
					if(vXPortalUser!=null){
						if(vXPortalUser.getLoginId()!=null && !vXPortalUser.getLoginId().equalsIgnoreCase(currentUser)){
							vXPortalUser.setStatus(entry.getValue());
							userMgr.updateUser(vXPortalUser);
						}
					}
				}
			}
		}
	}

	public void checkAdminAccess() {
		UserSessionBase session = ContextUtil.getCurrentUserSession();
		if (session != null) {
			if (!session.isUserAdmin()) {
				VXResponse vXResponse = new VXResponse();
				vXResponse.setStatusCode(HttpServletResponse.SC_UNAUTHORIZED);
				vXResponse.setMsgDesc("Operation" + " denied. LoggedInUser=" + (session != null ? session.getXXPortalUser().getId() : "Not Logged In")
						+ " ,isn't permitted to perform the action.");
				throw restErrorUtil.generateRESTException(vXResponse);
			}
		} else {
			VXResponse vXResponse = new VXResponse();
			vXResponse.setStatusCode(HttpServletResponse.SC_UNAUTHORIZED);
			vXResponse.setMsgDesc("Bad Credentials");
			throw restErrorUtil.generateRESTException(vXResponse);
		}
	}

	public void checkAccess(String loginID) {
		UserSessionBase session = ContextUtil.getCurrentUserSession();
		if (session != null) {
			if (!session.isUserAdmin() && !session.isKeyAdmin() && !session.getLoginId().equalsIgnoreCase(loginID)) {
				throw restErrorUtil.create403RESTException("Operation" + " denied. LoggedInUser=" + (session != null ? session.getXXPortalUser().getId() : "Not Logged In")
						+ " ,isn't permitted to perform the action.");
			}
		} else {
			VXResponse vXResponse = new VXResponse();
			vXResponse.setStatusCode(HttpServletResponse.SC_UNAUTHORIZED);
			vXResponse.setMsgDesc("Bad Credentials");
			throw restErrorUtil.generateRESTException(vXResponse);
		}
	}

	public VXPermMapList searchXPermMaps(SearchCriteria searchCriteria) {

		VXPermMapList returnList;
		UserSessionBase currentUserSession = ContextUtil.getCurrentUserSession();
		// If user is system admin
		if (currentUserSession != null && currentUserSession.isUserAdmin()) {
			returnList = super.searchXPermMaps(searchCriteria);
		} else {
			returnList = new VXPermMapList();
			int startIndex = searchCriteria.getStartIndex();
			int pageSize = searchCriteria.getMaxRows();
			searchCriteria.setStartIndex(0);
			searchCriteria.setMaxRows(Integer.MAX_VALUE);
			List<VXPermMap> resultList = xPermMapService.searchXPermMaps(searchCriteria).getVXPermMaps();

			List<VXPermMap> adminPermResourceList = new ArrayList<VXPermMap>();
			for (VXPermMap xXPermMap : resultList) {
				XXResource xRes = daoManager.getXXResource().getById(xXPermMap.getResourceId());
				VXResponse vXResponse = msBizUtil.hasPermission(xResourceService.populateViewBean(xRes),
						AppConstants.XA_PERM_TYPE_ADMIN);
				if (vXResponse.getStatusCode() == VXResponse.STATUS_SUCCESS) {
					adminPermResourceList.add(xXPermMap);
				}
			}

			if (adminPermResourceList.size() > 0) {
				populatePageList(adminPermResourceList, startIndex, pageSize, returnList);
			}
		}
		return returnList;
	}

	private void populatePageList(List<VXPermMap> permMapList, int startIndex, int pageSize, VXPermMapList vxPermMapList) {
		List<VXPermMap> onePageList = new ArrayList<VXPermMap>();
		for (int i = startIndex; i < pageSize + startIndex && i < permMapList.size(); i++) {
			VXPermMap vXPermMap = permMapList.get(i);
			onePageList.add(vXPermMap);
		}
		vxPermMapList.setVXPermMaps(onePageList);
		vxPermMapList.setStartIndex(startIndex);
		vxPermMapList.setPageSize(pageSize);
		vxPermMapList.setResultSize(onePageList.size());
		vxPermMapList.setTotalCount(permMapList.size());
	}

	public VXAuditMapList searchXAuditMaps(SearchCriteria searchCriteria) {

		VXAuditMapList returnList;
		UserSessionBase currentUserSession = ContextUtil.getCurrentUserSession();
		// If user is system admin
		if (currentUserSession != null && currentUserSession.isUserAdmin()) {
			returnList = super.searchXAuditMaps(searchCriteria);
		} else {
			returnList = new VXAuditMapList();
			int startIndex = searchCriteria.getStartIndex();
			int pageSize = searchCriteria.getMaxRows();
			searchCriteria.setStartIndex(0);
			searchCriteria.setMaxRows(Integer.MAX_VALUE);
			List<VXAuditMap> resultList = xAuditMapService.searchXAuditMaps(searchCriteria).getVXAuditMaps();

			List<VXAuditMap> adminAuditResourceList = new ArrayList<VXAuditMap>();
			for (VXAuditMap xXAuditMap : resultList) {
				XXResource xRes = daoManager.getXXResource().getById(xXAuditMap.getResourceId());
				VXResponse vXResponse = msBizUtil.hasPermission(xResourceService.populateViewBean(xRes),
						AppConstants.XA_PERM_TYPE_ADMIN);
				if (vXResponse.getStatusCode() == VXResponse.STATUS_SUCCESS) {
					adminAuditResourceList.add(xXAuditMap);
				}
			}

			if (adminAuditResourceList.size() > 0) {
				populatePageList(adminAuditResourceList, startIndex, pageSize, returnList);
			}
		}

		return returnList;
	}

	private void populatePageList(List<VXAuditMap> auditMapList, int startIndex, int pageSize,
			VXAuditMapList vxAuditMapList) {
		List<VXAuditMap> onePageList = new ArrayList<VXAuditMap>();
		for (int i = startIndex; i < pageSize + startIndex && i < auditMapList.size(); i++) {
			VXAuditMap vXAuditMap = auditMapList.get(i);
			onePageList.add(vXAuditMap);
		}
		vxAuditMapList.setVXAuditMaps(onePageList);
		vxAuditMapList.setStartIndex(startIndex);
		vxAuditMapList.setPageSize(pageSize);
		vxAuditMapList.setResultSize(onePageList.size());
		vxAuditMapList.setTotalCount(auditMapList.size());
	}

	public void checkAccessRoles(List<String> stringRolesList) {
		UserSessionBase session = ContextUtil.getCurrentUserSession();
                if (session != null && stringRolesList != null) {
			if (!session.isUserAdmin() && !session.isKeyAdmin()) {
				throw restErrorUtil.create403RESTException("Permission"
						+ " denied. LoggedInUser="
						+ (session != null ? session.getXXPortalUser().getId()
								: "Not Logged In")
						+ " ,isn't permitted to perform the action.");
                        } else {
                                if (!"rangerusersync".equals(session.getXXPortalUser()
                                                .getLoginId())) {// new logic for rangerusersync user
                                        if (session.isUserAdmin()
                                                        && stringRolesList
                                                                        .contains(RangerConstants.ROLE_KEY_ADMIN)) {
                                                throw restErrorUtil.create403RESTException("Permission"
                                                                + " denied. LoggedInUser="
                                                                + (session != null ? session.getXXPortalUser()
                                                                                .getId() : "")
                                                                + " isn't permitted to perform the action.");
                                        }
                                        if (session.isKeyAdmin()
                                                        && stringRolesList
                                                                        .contains(RangerConstants.ROLE_SYS_ADMIN)) {
                                                throw restErrorUtil.create403RESTException("Permission"
                                                                + " denied. LoggedInUser="
                                                                + (session != null ? session.getXXPortalUser()
                                                                                .getId() : "")
                                                                + " isn't permitted to perform the action.");
                                        }
                                } else {
                                        logger.info("LoggedInUser="
                                                        + (session != null ? session.getXXPortalUser()
                                                                        .getId() : "")
                                                        + " is permitted to perform the action");
				}
			}
                } else {
			VXResponse vXResponse = new VXResponse();
			vXResponse.setStatusCode(HttpServletResponse.SC_UNAUTHORIZED);
			vXResponse.setMsgDesc("Bad Credentials");
			throw restErrorUtil.generateRESTException(vXResponse);
		}
	}

	public VXStringList setUserRolesByExternalID(Long userId, List<VXString> vStringRolesList) {
		List<String> roleListNewProfile = new ArrayList<String>();
		if(vStringRolesList!=null){
			for (VXString vXString : vStringRolesList) {
				roleListNewProfile.add(vXString.getValue());
			}
		}
		checkAccessRoles(roleListNewProfile);
		VXUser vXUser=getXUser(userId);
		List<XXPortalUserRole> portalUserRoleList =null;
		if(vXUser!=null && roleListNewProfile.size()>0){
			VXPortalUser oldUserProfile = userMgr.getUserProfileByLoginId(vXUser.getName());
			if(oldUserProfile!=null){
				denySelfRoleChange(oldUserProfile.getLoginId());
				updateUserRolesPermissions(oldUserProfile,roleListNewProfile);
				portalUserRoleList = daoManager.getXXPortalUserRole().findByUserId(oldUserProfile.getId());
				return getStringListFromUserRoleList(portalUserRoleList);
			}else{
				throw restErrorUtil.createRESTException("User ID doesn't exist.", MessageEnums.INVALID_INPUT_DATA);
			}
		}else{
			throw restErrorUtil.createRESTException("User ID doesn't exist.", MessageEnums.INVALID_INPUT_DATA);
		}
	}

	public VXStringList setUserRolesByName(String userName, List<VXString> vStringRolesList) {
		List<String> roleListNewProfile = new ArrayList<String>();
		if(vStringRolesList!=null){
			for (VXString vXString : vStringRolesList) {
				roleListNewProfile.add(vXString.getValue());
			}
		}
		checkAccessRoles(roleListNewProfile);
		if(userName!=null && roleListNewProfile.size()>0){
			VXPortalUser oldUserProfile = userMgr.getUserProfileByLoginId(userName);
			if(oldUserProfile!=null){
				denySelfRoleChange(oldUserProfile.getLoginId());
				updateUserRolesPermissions(oldUserProfile,roleListNewProfile);
				List<XXPortalUserRole> portalUserRoleList = daoManager.getXXPortalUserRole().findByUserId(oldUserProfile.getId());
				return getStringListFromUserRoleList(portalUserRoleList);
			}else{
				throw restErrorUtil.createRESTException("Login ID doesn't exist.", MessageEnums.INVALID_INPUT_DATA);
			}
		}else{
			throw restErrorUtil.createRESTException("Login ID doesn't exist.", MessageEnums.INVALID_INPUT_DATA);
		}

	}

	public VXStringList getUserRolesByExternalID(Long userId) {
		VXUser vXUser=getXUser(userId);
		if(vXUser==null){
			throw restErrorUtil.createRESTException("Please provide a valid ID", MessageEnums.INVALID_INPUT_DATA);
		}
		checkAccess(vXUser.getName());
		List<XXPortalUserRole> portalUserRoleList =null;
		VXPortalUser oldUserProfile = userMgr.getUserProfileByLoginId(vXUser.getName());
		if(oldUserProfile!=null){
			portalUserRoleList = daoManager.getXXPortalUserRole().findByUserId(oldUserProfile.getId());
			return getStringListFromUserRoleList(portalUserRoleList);
		}else{
				throw restErrorUtil.createRESTException("User ID doesn't exist.", MessageEnums.INVALID_INPUT_DATA);
		}
	}

	public VXStringList getUserRolesByName(String userName) {
		VXPortalUser vXPortalUser=null;
		if(userName!=null && !userName.trim().isEmpty()){
			checkAccess(userName);
			vXPortalUser = userMgr.getUserProfileByLoginId(userName);
			if(vXPortalUser!=null && vXPortalUser.getUserRoleList()!=null){
				List<XXPortalUserRole> portalUserRoleList = daoManager.getXXPortalUserRole().findByUserId(vXPortalUser.getId());
				return getStringListFromUserRoleList(portalUserRoleList);
			}else{
				throw restErrorUtil.createRESTException("Please provide a valid userName", MessageEnums.INVALID_INPUT_DATA);
			}
		}else{
			throw restErrorUtil.createRESTException("Please provide a valid userName", MessageEnums.INVALID_INPUT_DATA);
		}
	}

	public void updateUserRolesPermissions(VXPortalUser oldUserProfile,List<String> roleListNewProfile){
		//update permissions start
		Collection<String> roleListUpdatedProfile =new ArrayList<String>();
		if (oldUserProfile != null && oldUserProfile.getId() != null) {
				Collection<String> roleListOldProfile = oldUserProfile.getUserRoleList();
				if(roleListNewProfile!=null && roleListOldProfile!=null){
					for (String role : roleListNewProfile) {
						if(role!=null && !roleListOldProfile.contains(role)){
							roleListUpdatedProfile.add(role);
						}
					}
				}
		}
		if(roleListUpdatedProfile!=null && roleListUpdatedProfile.size()>0){
			oldUserProfile.setUserRoleList(roleListUpdatedProfile);
			List<XXUserPermission> xuserPermissionList = daoManager
					.getXXUserPermission()
					.findByUserPermissionId(oldUserProfile.getId());
			if (xuserPermissionList!=null && xuserPermissionList.size()>0){
				for (XXUserPermission xXUserPermission : xuserPermissionList) {
					if (xXUserPermission != null) {
						xUserPermissionService.deleteResource(xXUserPermission.getId());
					}
				}
			}
			assignPermissionToUser(oldUserProfile,true);
			if(roleListUpdatedProfile!=null && roleListUpdatedProfile.size()>0){
				userMgr.updateRoles(oldUserProfile.getId(), oldUserProfile.getUserRoleList());
			}
		}
		//update permissions end
		}

	public VXStringList getStringListFromUserRoleList(
			List<XXPortalUserRole> listXXPortalUserRole) {
		if(listXXPortalUserRole==null){
			return null;
		}
		List<VXString> xStrList = new ArrayList<VXString>();
		VXString vXStr=null;
		for (XXPortalUserRole userRole : listXXPortalUserRole) {
			if(userRole!=null){
				vXStr = new VXString();
				vXStr.setValue(userRole.getUserRole());
				xStrList.add(vXStr);
			}
		}
		VXStringList vXStringList = new VXStringList(xStrList);
		return vXStringList;
	}

	public boolean hasAccess(String loginID) {
		UserSessionBase session = ContextUtil.getCurrentUserSession();
		if (session != null) {
			if(session.isUserAdmin() || session.getLoginId().equalsIgnoreCase(loginID)){
				return true;
			}
		}
		return false;
	}

	public VXUser getMaskedVXUser(VXUser vXUser) {
		if(vXUser!=null){
			if(vXUser.getGroupIdList()!=null && vXUser.getGroupIdList().size()>0){
				vXUser.setGroupIdList(new ArrayList<Long>());
			}
			if(vXUser.getGroupNameList()!=null && vXUser.getGroupNameList().size()>0){
				vXUser.setGroupNameList(getMaskedCollection(vXUser.getGroupNameList()));
			}
			if(vXUser.getUserRoleList()!=null && vXUser.getUserRoleList().size()>0){
				vXUser.setUserRoleList(getMaskedCollection(vXUser.getUserRoleList()));
			}
			vXUser.setUpdatedBy(AppConstants.Masked_String);
		}
		return vXUser;
	}

	public VXGroup getMaskedVXGroup(VXGroup vXGroup) {
        if(vXGroup!=null){
            vXGroup.setUpdatedBy(AppConstants.Masked_String);
        }
        return vXGroup;
	}

	@Override
	public VXUserList searchXUsers(SearchCriteria searchCriteria) {
		VXUserList vXUserList = new VXUserList();
		VXUser vXUserExactMatch = null;
		try{
			VXUserList vXUserListSort = new VXUserList();
			if(searchCriteria.getParamList() != null && searchCriteria.getParamList().get("name") != null){
				searchCriteria.setSortBy("name");
				vXUserListSort = xUserService.searchXUsers(searchCriteria);
				vXUserExactMatch = getXUserByUserName((String)searchCriteria.getParamList().get("name"));
			}
			int vXUserExactMatchwithSearchCriteria = 0;
			if(vXUserExactMatch != null){
				vXUserListSort = xUserService.searchXUsers(searchCriteria);
				HashMap<String, Object> searchCriteriaParamList = searchCriteria.getParamList();
				vXUserExactMatchwithSearchCriteria = 1;
				for(Map.Entry<String, Object> entry:searchCriteriaParamList.entrySet()){
					String caseKey=entry.getKey();
					switch (caseKey.toLowerCase()) {
						case "isvisible":
							Integer isVisible = vXUserExactMatch.getIsVisible();
							if(isVisible != null && !isVisible.equals(entry.getValue())){
								vXUserExactMatchwithSearchCriteria = -1;
							}
							break;
						case "status":
							Integer status = vXUserExactMatch.getStatus();
							if(status != null && !status.equals(entry.getValue())){
								vXUserExactMatchwithSearchCriteria = -1;
							}
							break;
						case "usersource":
							Integer userSource = vXUserExactMatch.getUserSource();
							if(userSource != null && !userSource.equals(entry.getValue())){
								vXUserExactMatchwithSearchCriteria = -1;
							}
							break;
						case "emailaddress":
							String email = vXUserExactMatch.getEmailAddress();
							if(email != null && !email.equals(entry.getValue())){
								vXUserExactMatchwithSearchCriteria = -1;
							}
							break;
						case "userrole":
							if(vXUserExactMatch.getUserRoleList() != null && !vXUserExactMatch.getUserRoleList().contains(entry.getValue())){
								vXUserExactMatchwithSearchCriteria = -1;
							}
							break;
						case "userrolelist":
							@SuppressWarnings("unchecked")
							Collection<String> userrolelist = (Collection<String>) entry.getValue();
							if(!CollectionUtils.isEmpty(userrolelist)){
								for(String role:userrolelist){
									if(vXUserExactMatch.getUserRoleList() != null && vXUserExactMatch.getUserRoleList().contains(role)){
										vXUserExactMatchwithSearchCriteria = 1;
										break;
									}
									else{
										vXUserExactMatchwithSearchCriteria = -1;
									}
								}
							}
							break;
						default:
							logger.warn("XUserMgr.searchXUsers: unexpected searchCriteriaParam:" + caseKey);
							break;
					}
					if(vXUserExactMatchwithSearchCriteria == -1){
						break;
					}
				}
			}
			if(vXUserExactMatchwithSearchCriteria == 1){
				VXGroupList groups = getXUserGroups(vXUserExactMatch.getId());
				if(groups.getListSize() > 0){
					Collection<String> groupNameList = new ArrayList<String>();
					Collection<Long> groupIdList = new ArrayList<Long>();
					for(VXGroup group:groups.getList()){
						groupIdList.add(group.getId());
						groupNameList.add(group.getName());
					}
					vXUserExactMatch.setGroupIdList(groupIdList);
					vXUserExactMatch.setGroupNameList(groupNameList);
				}
				List<VXUser> vXUsers = new ArrayList<VXUser>();
				if(searchCriteria.getStartIndex() == 0){
					vXUsers.add(0,vXUserExactMatch);
				}
				for(VXUser vxUser:vXUserListSort.getVXUsers()){
					if(vXUserExactMatch.getId()!=null && vxUser!=null){
						if(!vXUserExactMatch.getId().equals(vxUser.getId())){
							vXUsers.add(vxUser);
						}
					}
				}
				vXUserList.setVXUsers(vXUsers);
				vXUserList.setStartIndex(searchCriteria.getStartIndex());
				vXUserList.setResultSize(vXUserList.getVXUsers().size());
				vXUserList.setTotalCount(vXUserListSort.getTotalCount());
				vXUserList.setPageSize(searchCriteria.getMaxRows());
				vXUserList.setSortBy(searchCriteria.getSortBy());
				vXUserList.setSortType(searchCriteria.getSortType());
			}
		} catch (Exception e){
			logger.error("Error getting the exact match of user =>"+e);
		}
		if(vXUserList.getVXUsers().isEmpty()) {
			searchCriteria.setSortBy("id");
			vXUserList = xUserService.searchXUsers(searchCriteria);
		}
		if(vXUserList!=null && !hasAccessToModule(RangerConstants.MODULE_USER_GROUPS)){
			List<VXUser> vXUsers = new ArrayList<VXUser>();
			if(vXUserList!=null && vXUserList.getListSize()>0){
				for(VXUser vXUser:vXUserList.getList()){
					vXUser=getMaskedVXUser(vXUser);
					vXUsers.add(vXUser);
				}
				vXUserList.setVXUsers(vXUsers);
			}
		}
		return vXUserList;
	}

	@Override
	public VXGroupList searchXGroups(SearchCriteria searchCriteria) {
		VXGroupList vXGroupList= new VXGroupList();
		VXGroup vXGroupExactMatch = null;
		try{
			VXGroupList vXGroupListSort= new VXGroupList();
			if(searchCriteria.getParamList() != null && searchCriteria.getParamList().get("name") != null){
				searchCriteria.setSortBy("name");
				vXGroupListSort = xGroupService.searchXGroups(searchCriteria);
				vXGroupExactMatch = getGroupByGroupName((String)searchCriteria.getParamList().get("name"));
			}
			int vXGroupExactMatchwithSearchCriteria = 0;
			if(vXGroupExactMatch != null){
				HashMap<String, Object> searchCriteriaParamList = searchCriteria.getParamList();
				vXGroupExactMatchwithSearchCriteria = 1;
				for (Map.Entry<String, Object> entry: searchCriteriaParamList.entrySet()){
					String caseKey=entry.getKey();
					switch (caseKey.toLowerCase()) {
						case "isvisible":
							Integer isVisible = vXGroupExactMatch.getIsVisible();
							if(isVisible != null && !isVisible.equals(entry.getValue())){
								vXGroupExactMatchwithSearchCriteria = -1;
							}
							break;
						case "groupsource":
							Integer groupsource = vXGroupExactMatch.getGroupSource();
							if(groupsource != null && !groupsource.equals(entry.getValue())){
								vXGroupExactMatchwithSearchCriteria = -1;
							}
							break;
						default:
							logger.warn("XUserMgr.searchXGroups: unexpected searchCriteriaParam:" + caseKey);
							break;
					}
					if(vXGroupExactMatchwithSearchCriteria == -1){
						break;
					}
				}
			}
			if(vXGroupExactMatchwithSearchCriteria == 1){
				List<VXGroup> vXGroups = new ArrayList<VXGroup>();
				if(searchCriteria.getStartIndex() == 0){
					vXGroups.add(0,vXGroupExactMatch);
				}
				for(VXGroup vXGroup:vXGroupListSort.getList()){
					if(vXGroupExactMatch.getId() != null && vXGroup != null){
						if(!vXGroupExactMatch.getId().equals(vXGroup.getId())){
							vXGroups.add(vXGroup);
						}
					}
				}
				vXGroupList.setVXGroups(vXGroups);
				vXGroupList.setStartIndex(searchCriteria.getStartIndex());
				vXGroupList.setResultSize(vXGroupList.getList().size());
				vXGroupList.setTotalCount(vXGroupListSort.getTotalCount());
				vXGroupList.setPageSize(searchCriteria.getMaxRows());
				vXGroupList.setSortBy(searchCriteria.getSortBy());
				vXGroupList.setSortType(searchCriteria.getSortType());
			}
		} catch (Exception e){
			logger.error("Error getting the exact match of group =>"+e);
		}
		if(vXGroupList.getList().isEmpty()) {
			searchCriteria.setSortBy("id");
			vXGroupList=xGroupService.searchXGroups(searchCriteria);
		}
                UserSessionBase userSession = ContextUtil.getCurrentUserSession();
                if (userSession != null && userSession.getLoginId() != null) {
                                        VXUser loggedInVXUser = xUserService.getXUserByUserName(userSession
                                                        .getLoginId());
                                        if (loggedInVXUser != null) {
                                                if (loggedInVXUser.getUserRoleList().size() == 1
                                                                && loggedInVXUser.getUserRoleList().contains(
                                                                                RangerConstants.ROLE_USER)) {

                                                        List<VXGroup> updatedList = new ArrayList<VXGroup>();

                                                        List<Long> listGroupId = daoManager.getXXGroupUser()
                                                                        .findGroupIdListByUserId(loggedInVXUser.getId());

                                                        for (VXGroup group : vXGroupList.getList()) {
                                                                if (listGroupId.contains(group.getId())) {
                                                                        updatedList.add(group);
                                                                }
                                                        }
                                                        logger.info("Logged-In user having user role will be able to fetch his own groups details.");
                                                        vXGroupList.setVXGroups(updatedList);

                                                }
                                        }
                }
		if(vXGroupList!=null && !hasAccessToModule(RangerConstants.MODULE_USER_GROUPS)){
			if(vXGroupList!=null && vXGroupList.getListSize()>0){
				List<VXGroup> listMasked=new ArrayList<VXGroup>();
				for(VXGroup vXGroup:vXGroupList.getList()){
					vXGroup=getMaskedVXGroup(vXGroup);
					listMasked.add(vXGroup);
				}
				vXGroupList.setVXGroups(listMasked);
			}
		}
		return vXGroupList;
	}

	public Collection<String> getMaskedCollection(Collection<String> listunMasked){
        List<String> listMasked=new ArrayList<String>();
        if(listunMasked!=null) {
            for(int i = 0; i < listunMasked.size(); i++) {
                listMasked.add(AppConstants.Masked_String);
            }
        }
        return listMasked;
	}

	public boolean hasAccessToModule(String moduleName){
		UserSessionBase userSession = ContextUtil.getCurrentUserSession();
		if (userSession != null && userSession.getLoginId()!=null){
			VXUser vxUser = xUserService.getXUserByUserName(userSession.getLoginId());
			if(vxUser!=null){
				List<String> permissionList = daoManager.getXXModuleDef().findAccessibleModulesByUserId(userSession.getUserId(), vxUser.getId());
				if(permissionList!=null && permissionList.contains(moduleName)){
					return true;
				}
			}
		}
		return false;
	}

	public void deleteXGroup(Long id, boolean force) {
		checkAdminAccess();
		XXGroupDao xXGroupDao = daoManager.getXXGroup();
		XXGroup xXGroup = xXGroupDao.getById(id);
		VXGroup vXGroup = xGroupService.populateViewBean(xXGroup);
		if (vXGroup == null || StringUtil.isEmpty(vXGroup.getName())) {
			throw restErrorUtil.createRESTException("Group ID doesn't exist.", MessageEnums.INVALID_INPUT_DATA);
		}
		if(logger.isDebugEnabled()){
			logger.info("Force delete status="+force+" for group="+vXGroup.getName());
		}

		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addParam("xGroupId", id);
		VXGroupUserList vxGroupUserList = searchXGroupUsers(searchCriteria);

		searchCriteria = new SearchCriteria();
		searchCriteria.addParam("groupId", id);
		VXPermMapList vXPermMapList = searchXPermMaps(searchCriteria);

		searchCriteria = new SearchCriteria();
		searchCriteria.addParam("groupId", id);
		VXAuditMapList vXAuditMapList = searchXAuditMaps(searchCriteria);

		XXGroupPermissionDao xXGroupPermissionDao=daoManager.getXXGroupPermission();
		List<XXGroupPermission> xXGroupPermissions=xXGroupPermissionDao.findByGroupId(id);

		XXGroupGroupDao xXGroupGroupDao = daoManager.getXXGroupGroup();
		List<XXGroupGroup> xXGroupGroups = xXGroupGroupDao.findByGroupId(id);

		XXPolicyDao xXPolicyDao = daoManager.getXXPolicy();
		List<XXPolicy> xXPolicyList = xXPolicyDao.findByGroupId(id);
		logger.warn("Deleting GROUP : "+vXGroup.getName());
		if (force) {
			//delete XXGroupUser records of matching group
			XXGroupUserDao xGroupUserDao = daoManager.getXXGroupUser();
			XXUserDao xXUserDao = daoManager.getXXUser();
			XXUser xXUser =null;
			for (VXGroupUser groupUser : vxGroupUserList.getList()) {
				if(groupUser!=null){
					xXUser=xXUserDao.getById(groupUser.getUserId());
					if(xXUser!=null){
						logger.warn("Removing user '" + xXUser.getName() + "' from group '" + groupUser.getName() + "'");
					}
					xGroupUserDao.remove(groupUser.getId());
				}
			}
			//delete XXPermMap records of matching group
			XXPermMapDao xXPermMapDao = daoManager.getXXPermMap();
			XXResourceDao xXResourceDao = daoManager.getXXResource();
			XXResource xXResource =null;
			for (VXPermMap vXPermMap : vXPermMapList.getList()) {
				if(vXPermMap!=null){
					xXResource=xXResourceDao.getById(vXPermMap.getResourceId());
					if(xXResource!=null){
						logger.warn("Deleting '" + AppConstants.getLabelFor_XAPermType(vXPermMap.getPermType()) + "' permission from policy ID='" + vXPermMap.getResourceId() + "' for group '" + vXPermMap.getGroupName() + "'");
					}
					xXPermMapDao.remove(vXPermMap.getId());
				}
			}
			//delete XXAuditMap records of matching group
			XXAuditMapDao xXAuditMapDao = daoManager.getXXAuditMap();
			for (VXAuditMap vXAuditMap : vXAuditMapList.getList()) {
				if(vXAuditMap!=null){
					xXResource=xXResourceDao.getById(vXAuditMap.getResourceId());
					xXAuditMapDao.remove(vXAuditMap.getId());
				}
			}
			//delete XXGroupGroupDao records of group-group mapping
			for (XXGroupGroup xXGroupGroup : xXGroupGroups) {
				if(xXGroupGroup!=null){
					XXGroup xXGroupParent=xXGroupDao.getById(xXGroupGroup.getParentGroupId());
					XXGroup xXGroupChild=xXGroupDao.getById(xXGroupGroup.getGroupId());
					if(xXGroupParent!=null && xXGroupChild!=null){
						logger.warn("Removing group '" + xXGroupChild.getName() + "' from group '" + xXGroupParent.getName() + "'");
					}
					xXGroupGroupDao.remove(xXGroupGroup.getId());
				}
			}
			//delete XXPolicyItemGroupPerm records of group
			for (XXPolicy xXPolicy : xXPolicyList) {
				RangerPolicy rangerPolicy = policyService.getPopulatedViewObject(xXPolicy);
				List<RangerPolicyItem> policyItems = rangerPolicy.getPolicyItems();
				removeUserGroupReferences(policyItems,null,vXGroup.getName());
				rangerPolicy.setPolicyItems(policyItems);

				List<RangerPolicyItem> denyPolicyItems = rangerPolicy.getDenyPolicyItems();
				removeUserGroupReferences(denyPolicyItems,null,vXGroup.getName());
				rangerPolicy.setDenyPolicyItems(denyPolicyItems);

				List<RangerPolicyItem> allowExceptions = rangerPolicy.getAllowExceptions();
				removeUserGroupReferences(allowExceptions,null,vXGroup.getName());
				rangerPolicy.setAllowExceptions(allowExceptions);

				List<RangerPolicyItem> denyExceptions = rangerPolicy.getDenyExceptions();
				removeUserGroupReferences(denyExceptions,null,vXGroup.getName());
				rangerPolicy.setDenyExceptions(denyExceptions);

				List<RangerDataMaskPolicyItem> dataMaskItems = rangerPolicy.getDataMaskPolicyItems();
				removeUserGroupReferences(dataMaskItems,null,vXGroup.getName());
				rangerPolicy.setDataMaskPolicyItems(dataMaskItems);

				List<RangerRowFilterPolicyItem> rowFilterItems = rangerPolicy.getRowFilterPolicyItems();
				removeUserGroupReferences(rowFilterItems,null,vXGroup.getName());
				rangerPolicy.setRowFilterPolicyItems(rowFilterItems);

				try {
					svcStore.updatePolicy(rangerPolicy);
				} catch (Throwable excp) {
					logger.error("updatePolicy(" + rangerPolicy + ") failed", excp);
					restErrorUtil.createRESTException(excp.getMessage());
				}
			}
			if(CollectionUtils.isNotEmpty(xXGroupPermissions)){
				for (XXGroupPermission xXGroupPermission : xXGroupPermissions) {
					if(xXGroupPermission!=null){
						XXModuleDef xXModuleDef=daoManager.getXXModuleDef().findByModuleId(xXGroupPermission.getModuleId());
						if(xXModuleDef!=null){
							logger.warn("Deleting '" + xXModuleDef.getModule() + "' module permission for group '" + xXGroup.getName() + "'");
						}
						xXGroupPermissionDao.remove(xXGroupPermission.getId());
					}
				}
			}
			//delete XXGroup
			xXGroupDao.remove(id);
			//Create XXTrxLog
			List<XXTrxLog> xXTrxLogsXXGroup = xGroupService.getTransactionLog(xGroupService.populateViewBean(xXGroup),
					"delete");
			xaBizUtil.createTrxLog(xXTrxLogsXXGroup);
		} else {
			boolean hasReferences=false;

			if(vxGroupUserList.getListSize()>0){
				hasReferences=true;
			}
			if(hasReferences==false && CollectionUtils.isNotEmpty(xXPolicyList)){
				hasReferences=true;
			}
			if(hasReferences==false && vXPermMapList.getListSize()>0){
				hasReferences=true;
			}
			if(hasReferences==false && vXAuditMapList.getListSize()>0){
				hasReferences=true;
			}
			if(hasReferences==false && CollectionUtils.isNotEmpty(xXGroupGroups)){
				hasReferences=true;
			}
			if(hasReferences==false && CollectionUtils.isNotEmpty(xXGroupPermissions)){
				hasReferences=true;
			}

			if(hasReferences){ //change visibility to Hidden
				if(vXGroup.getIsVisible()==RangerCommonEnums.IS_VISIBLE){
					vXGroup.setIsVisible(RangerCommonEnums.IS_HIDDEN);
					xGroupService.updateResource(vXGroup);
				}
			}else{
				//delete XXGroup
				xXGroupDao.remove(id);
				//Create XXTrxLog
				List<XXTrxLog> xXTrxLogsXXGroup = xGroupService.getTransactionLog(xGroupService.populateViewBean(xXGroup),
						"delete");
				xaBizUtil.createTrxLog(xXTrxLogsXXGroup);
			}
		}
	}

        public synchronized void deleteXUser(Long id, boolean force) {
		checkAdminAccess();
		XXUserDao xXUserDao = daoManager.getXXUser();
		XXUser xXUser =	xXUserDao.getById(id);
		VXUser vXUser =	xUserService.populateViewBean(xXUser);
		if(vXUser==null ||StringUtil.isEmpty(vXUser.getName())){
			throw restErrorUtil.createRESTException("No user found with id=" + id);
		}
		XXPortalUserDao xXPortalUserDao=daoManager.getXXPortalUser();
		XXPortalUser xXPortalUser=xXPortalUserDao.findByLoginId(vXUser.getName().trim());
		VXPortalUser vXPortalUser=null;
		if(xXPortalUser!=null){
			vXPortalUser=xPortalUserService.populateViewBean(xXPortalUser);
		}
		if(vXPortalUser==null ||StringUtil.isEmpty(vXPortalUser.getLoginId())){
			throw restErrorUtil.createRESTException("No user found with id=" + id);
		}
		if (logger.isDebugEnabled()) {
			logger.debug("Force delete status="+force+" for user="+vXUser.getName());
		}
		restrictSelfAccountDeletion(vXUser.getName().trim());
		SearchCriteria searchCriteria = new SearchCriteria();
		searchCriteria.addParam("xUserId", id);
		VXGroupUserList vxGroupUserList = searchXGroupUsers(searchCriteria);

		searchCriteria = new SearchCriteria();
		searchCriteria.addParam("userId", id);
		VXPermMapList vXPermMapList = searchXPermMaps(searchCriteria);

		searchCriteria = new SearchCriteria();
		searchCriteria.addParam("userId", id);
		VXAuditMapList vXAuditMapList = searchXAuditMaps(searchCriteria);

		long xXPortalUserId=0;
		xXPortalUserId=vXPortalUser.getId();
		XXAuthSessionDao xXAuthSessionDao=daoManager.getXXAuthSession();
		XXUserPermissionDao xXUserPermissionDao=daoManager.getXXUserPermission();
		XXPortalUserRoleDao xXPortalUserRoleDao=daoManager.getXXPortalUserRole();
		List<XXAuthSession> xXAuthSessions=xXAuthSessionDao.getAuthSessionByUserId(xXPortalUserId);
		List<XXUserPermission> xXUserPermissions=xXUserPermissionDao.findByUserPermissionId(xXPortalUserId);
		List<XXPortalUserRole> xXPortalUserRoles=xXPortalUserRoleDao.findByUserId(xXPortalUserId);

		XXPolicyDao xXPolicyDao = daoManager.getXXPolicy();
		List<XXPolicy> xXPolicyList=xXPolicyDao.findByUserId(id);
		logger.warn("Deleting User : "+vXUser.getName());
		if (force) {
			//delete XXGroupUser mapping
			XXGroupUserDao xGroupUserDao = daoManager.getXXGroupUser();
			for (VXGroupUser groupUser : vxGroupUserList.getList()) {
				if(groupUser!=null){
					logger.warn("Removing user '" + vXUser.getName() + "' from group '" + groupUser.getName() + "'");
					xGroupUserDao.remove(groupUser.getId());
				}
			}
			//delete XXPermMap records of user
			XXPermMapDao xXPermMapDao = daoManager.getXXPermMap();
			for (VXPermMap vXPermMap : vXPermMapList.getList()) {
				if(vXPermMap!=null){
					logger.warn("Deleting '" + AppConstants.getLabelFor_XAPermType(vXPermMap.getPermType()) + "' permission from policy ID='" + vXPermMap.getResourceId() + "' for user '" + vXPermMap.getUserName() + "'");
					xXPermMapDao.remove(vXPermMap.getId());
				}
			}
			//delete XXAuditMap records of user
			XXAuditMapDao xXAuditMapDao = daoManager.getXXAuditMap();
			for (VXAuditMap vXAuditMap : vXAuditMapList.getList()) {
				if(vXAuditMap!=null){
					xXAuditMapDao.remove(vXAuditMap.getId());
				}
			}
			//delete XXPortalUser references
			if(vXPortalUser!=null){
				xPortalUserService.updateXXPortalUserReferences(xXPortalUserId);
				if(xXAuthSessions!=null && xXAuthSessions.size()>0){
					logger.warn("Deleting " + xXAuthSessions.size() + " login session records for user '" +  vXPortalUser.getLoginId() + "'");
				}
				for (XXAuthSession xXAuthSession : xXAuthSessions) {
					xXAuthSessionDao.remove(xXAuthSession.getId());
				}
				for (XXUserPermission xXUserPermission : xXUserPermissions) {
					if(xXUserPermission!=null){
						XXModuleDef xXModuleDef=daoManager.getXXModuleDef().findByModuleId(xXUserPermission.getModuleId());
						if(xXModuleDef!=null){
							logger.warn("Deleting '" + xXModuleDef.getModule() + "' module permission for user '" + vXPortalUser.getLoginId() + "'");
						}
						xXUserPermissionDao.remove(xXUserPermission.getId());
					}
				}
				for (XXPortalUserRole xXPortalUserRole : xXPortalUserRoles) {
					if(xXPortalUserRole!=null){
						logger.warn("Deleting '" + xXPortalUserRole.getUserRole() + "' role for user '" + vXPortalUser.getLoginId() + "'");
						xXPortalUserRoleDao.remove(xXPortalUserRole.getId());
					}
				}
			}
			//delete XXPolicyItemUserPerm records of user
			for(XXPolicy xXPolicy:xXPolicyList){
				RangerPolicy rangerPolicy = policyService.getPopulatedViewObject(xXPolicy);
				List<RangerPolicyItem> policyItems = rangerPolicy.getPolicyItems();
				removeUserGroupReferences(policyItems,vXUser.getName(),null);
				rangerPolicy.setPolicyItems(policyItems);

				List<RangerPolicyItem> denyPolicyItems = rangerPolicy.getDenyPolicyItems();
				removeUserGroupReferences(denyPolicyItems,vXUser.getName(),null);
				rangerPolicy.setDenyPolicyItems(denyPolicyItems);

				List<RangerPolicyItem> allowExceptions = rangerPolicy.getAllowExceptions();
				removeUserGroupReferences(allowExceptions,vXUser.getName(),null);
				rangerPolicy.setAllowExceptions(allowExceptions);

				List<RangerPolicyItem> denyExceptions = rangerPolicy.getDenyExceptions();
				removeUserGroupReferences(denyExceptions,vXUser.getName(),null);
				rangerPolicy.setDenyExceptions(denyExceptions);

				List<RangerDataMaskPolicyItem> dataMaskItems = rangerPolicy.getDataMaskPolicyItems();
				removeUserGroupReferences(dataMaskItems,vXUser.getName(),null);
				rangerPolicy.setDataMaskPolicyItems(dataMaskItems);

				List<RangerRowFilterPolicyItem> rowFilterItems = rangerPolicy.getRowFilterPolicyItems();
				removeUserGroupReferences(rowFilterItems,vXUser.getName(),null);
				rangerPolicy.setRowFilterPolicyItems(rowFilterItems);

				try{
					svcStore.updatePolicy(rangerPolicy);
				}catch(Throwable excp) {
					logger.error("updatePolicy(" + rangerPolicy + ") failed", excp);
					throw restErrorUtil.createRESTException(excp.getMessage());
				}
			}
			//delete XXUser entry of user
			xXUserDao.remove(id);
			//delete XXPortal entry of user
			logger.warn("Deleting Portal User : "+vXPortalUser.getLoginId());
			xXPortalUserDao.remove(xXPortalUserId);
			List<XXTrxLog> trxLogList =xUserService.getTransactionLog(xUserService.populateViewBean(xXUser), "delete");
			xaBizUtil.createTrxLog(trxLogList);
			if (xXPortalUser != null) {
				trxLogList=xPortalUserService
						.getTransactionLog(xPortalUserService.populateViewBean(xXPortalUser), "delete");
				xaBizUtil.createTrxLog(trxLogList);
			}
		} else {
			boolean hasReferences=false;

			if(vxGroupUserList!=null && vxGroupUserList.getListSize()>0){
				hasReferences=true;
			}
			if(hasReferences==false && xXPolicyList!=null && xXPolicyList.size()>0){
				hasReferences=true;
			}
			if(hasReferences==false && vXPermMapList!=null && vXPermMapList.getListSize()>0){
				hasReferences=true;
			}
			if(hasReferences==false && vXAuditMapList!=null && vXAuditMapList.getListSize()>0){
				hasReferences=true;
			}
			if(hasReferences==false && xXAuthSessions!=null && xXAuthSessions.size()>0){
				hasReferences=true;
			}
			if(hasReferences==false && xXUserPermissions!=null && xXUserPermissions.size()>0){
				hasReferences=true;
			}
			if(hasReferences==false && xXPortalUserRoles!=null && xXPortalUserRoles.size()>0){
				hasReferences=true;
			}
			if(hasReferences){
				if(vXUser.getIsVisible()!=RangerCommonEnums.IS_HIDDEN){
					logger.info("Updating visibility of user '"+vXUser.getName()+"' to Hidden!");
					vXUser.setIsVisible(RangerCommonEnums.IS_HIDDEN);
					xUserService.updateResource(vXUser);
				}
			}else{
				xPortalUserService.updateXXPortalUserReferences(xXPortalUserId);
				//delete XXUser entry of user
				xXUserDao.remove(id);
				//delete XXPortal entry of user
				logger.warn("Deleting Portal User : "+vXPortalUser.getLoginId());
				xXPortalUserDao.remove(xXPortalUserId);
				List<XXTrxLog> trxLogList =xUserService.getTransactionLog(xUserService.populateViewBean(xXUser), "delete");
				xaBizUtil.createTrxLog(trxLogList);
				trxLogList=xPortalUserService.getTransactionLog(xPortalUserService.populateViewBean(xXPortalUser), "delete");
				xaBizUtil.createTrxLog(trxLogList);
			}
		}
	}

	private <T extends RangerPolicyItem> void removeUserGroupReferences(List<T> policyItems, String user, String group) {
		List<T> itemsToRemove = null;
		for(T policyItem : policyItems) {
			if(!StringUtil.isEmpty(user)) {
				policyItem.getUsers().remove(user);
			}
			if(!StringUtil.isEmpty(group)) {
				policyItem.getGroups().remove(group);
			}
			if(policyItem.getUsers().isEmpty() && policyItem.getGroups().isEmpty()) {
				if(itemsToRemove == null) {
					itemsToRemove = new ArrayList<T>();
				}
				itemsToRemove.add(policyItem);
			}
		}
		if(CollectionUtils.isNotEmpty(itemsToRemove)) {
			policyItems.removeAll(itemsToRemove);
		}
	}

	public void restrictSelfAccountDeletion(String loginID) {
		UserSessionBase session = ContextUtil.getCurrentUserSession();
		if (session != null) {
			if (!session.isUserAdmin()) {
				throw restErrorUtil.create403RESTException("Operation denied. LoggedInUser= "+session.getXXPortalUser().getLoginId() + " isn't permitted to perform the action.");
			}else{
				if(!StringUtil.isEmpty(loginID) && loginID.equals(session.getLoginId())){
					throw restErrorUtil.create403RESTException("Operation denied. LoggedInUser= "+session.getXXPortalUser().getLoginId() + " isn't permitted to delete his own profile.");
				}
			}
		} else {
			VXResponse vXResponse = new VXResponse();
			vXResponse.setStatusCode(HttpServletResponse.SC_UNAUTHORIZED);
			vXResponse.setMsgDesc("Bad Credentials");
			throw restErrorUtil.generateRESTException(vXResponse);
		}
	}

	@Transactional(readOnly = false, propagation = Propagation.REQUIRED)
	public VXUser createServiceConfigUser(String userName){
		if (userName == null || "null".equalsIgnoreCase(userName) || userName.trim().isEmpty()) {
			logger.error("User Name: "+userName);
			throw restErrorUtil.createRESTException("Please provide a valid username.",MessageEnums.INVALID_INPUT_DATA);
		}
		VXUser vXUser = null;
		VXPortalUser vXPortalUser=null;
		XXUser xxUser = daoManager.getXXUser().findByUserName(userName);
		XXPortalUser xXPortalUser = daoManager.getXXPortalUser().findByLoginId(userName);
		String actualPassword = "";
		if(xxUser!=null){
			vXUser = xUserService.populateViewBean(xxUser);
			return vXUser;
		}
		if(xxUser==null){
			vXUser=new VXUser();
			vXUser.setName(userName);
			vXUser.setUserSource(RangerCommonEnums.USER_EXTERNAL);
			vXUser.setDescription(vXUser.getName());
			actualPassword = vXUser.getPassword();
		}
		if(xXPortalUser==null){
			vXPortalUser=new VXPortalUser();
			vXPortalUser.setLoginId(userName);
			vXPortalUser.setEmailAddress(vXUser.getEmailAddress());
			vXPortalUser.setFirstName(vXUser.getFirstName());
			vXPortalUser.setLastName(vXUser.getLastName());
			vXPortalUser.setPassword(vXUser.getPassword());
			vXPortalUser.setUserSource(RangerCommonEnums.USER_EXTERNAL);
			ArrayList<String> roleList = new ArrayList<String>();
			roleList.add(RangerConstants.ROLE_USER);
			vXPortalUser.setUserRoleList(roleList);
			xXPortalUser = userMgr.mapVXPortalUserToXXPortalUser(vXPortalUser);
			xXPortalUser=userMgr.createUser(xXPortalUser, RangerCommonEnums.STATUS_ENABLED, roleList);
		}
		VXUser createdXUser=null;
		if(xxUser==null && vXUser!=null){
			try{
				createdXUser = xUserService.createResource(vXUser);
			}catch(Exception ex){
				logger.error("Error creating user: "+createdXUser.getName(),ex);
			}
		}
		if(createdXUser!=null){
			try{
				logger.info("User created: "+createdXUser.getName());
				createdXUser.setPassword(actualPassword);
				List<XXTrxLog> trxLogList = xUserService.getTransactionLog(createdXUser, "create");
				String hiddenPassword = PropertiesUtil.getProperty("ranger.password.hidden", "*****");
				createdXUser.setPassword(hiddenPassword);
				xaBizUtil.createTrxLog(trxLogList);
				if(xXPortalUser!=null){
					vXPortalUser=userMgr.mapXXPortalUserToVXPortalUserForDefaultAccount(xXPortalUser);
					assignPermissionToUser(vXPortalUser, true);
				}
			}catch(Exception ex){
				logger.error("Error while assigning permissions to user: "+createdXUser.getName(),ex);
			}
		}else{
			xxUser = daoManager.getXXUser().findByUserName(userName);
			if(xxUser!=null){
				createdXUser = xUserService.populateViewBean(xxUser);
			}
		}
		return createdXUser;
        }
        private void validatePassword(VXUser vXUser) {
                if (vXUser.getPassword() != null && !vXUser.getPassword().isEmpty()) {
                        boolean checkPassword = false;
                        String pattern = "(?=.*[0-9])(?=.*[a-zA-Z]).{8,}";
                        checkPassword = vXUser.getPassword().trim().matches(pattern);
                        if (!checkPassword) {
                                logger.warn("validatePassword(). Password should be minimum 8 characters with min one alphabet and one numeric.");
                                throw restErrorUtil.createRESTException("serverMsg.xuserMgrValidatePassword", MessageEnums.INVALID_PASSWORD, null, "Password should be minimum 8 characters with min one alphabet and one numeric", null);
                        }
                } else {
                        logger.warn("validatePassword(). Password cannot be blank/null.");
                        throw restErrorUtil.createRESTException("serverMsg.xuserMgrValidatePassword", MessageEnums.INVALID_PASSWORD, null, "Password cannot be blank/null", null);
                }
        }

        private boolean hasAccessToGetUserInfo(VXUser requestedVXUser) {
                                UserSessionBase userSession = ContextUtil.getCurrentUserSession();
                                if (userSession != null && userSession.getLoginId() != null) {
                                        VXUser loggedInVXUser = xUserService.getXUserByUserName(userSession
                                                        .getLoginId());
                                        if (loggedInVXUser != null) {
                                                if (loggedInVXUser.getUserRoleList().size() == 1
                                                                && loggedInVXUser.getUserRoleList().contains(
                                                                                RangerConstants.ROLE_USER)) {

                                                        return requestedVXUser.getId().equals(loggedInVXUser.getId()) ? true : false;

                                                }else{
                                                        return true;
                                                }
                                        }
                                }
                                return false;
                        }
        public void denySelfRoleChange(String userName) {
            UserSessionBase session = ContextUtil.getCurrentUserSession();
            if (session != null && session.getXXPortalUser()!=null) {
                if (userName.equals(session.getXXPortalUser().getLoginId())) {
                    throw restErrorUtil.create403RESTException("Permission"
                            + " denied. LoggedInUser="
                            + (session != null ? session.getXXPortalUser().getId()
                                    : "Not Logged In")
                            + " ,isn't permitted to change its own role.");
                }
            }
	}
}
