package pwc.taxtech.atms.service.impl;

import io.jsonwebtoken.lang.Collections;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import pwc.taxtech.atms.common.CommonConstants;
import pwc.taxtech.atms.common.CommonUtils;
import pwc.taxtech.atms.common.OperateLogType;
import pwc.taxtech.atms.common.OperationAction;
import pwc.taxtech.atms.common.OperationModule;
import pwc.taxtech.atms.common.RoleSourceEnum;
import pwc.taxtech.atms.common.ServiceTypeEnum;
import pwc.taxtech.atms.constant.DimensionConstant;
import pwc.taxtech.atms.dpo.DimensionParamDto;
import pwc.taxtech.atms.dpo.DimensionValueOrgDto;
import pwc.taxtech.atms.dpo.OrganizationDto;
import pwc.taxtech.atms.dpo.RoleInfo;
import pwc.taxtech.atms.dpo.UnionDimensionValueOrg;
import pwc.taxtech.atms.dpo.UserDto;
import pwc.taxtech.atms.dpo.UserOrgDto;
import pwc.taxtech.atms.dpo.UserOrgRoleDto;
import pwc.taxtech.atms.dpo.UserRoleInfo;
import pwc.taxtech.atms.dto.OperationResultDto;
import pwc.taxtech.atms.dto.RoleCategoryDto;
import pwc.taxtech.atms.dto.UpdateLogParams;
import pwc.taxtech.atms.dto.dimension.DimensionValueUpdateDto;
import pwc.taxtech.atms.dto.dimension.SimpleDimensionDto;
import pwc.taxtech.atms.dto.navtree.NavTreeDto;
import pwc.taxtech.atms.dto.permission.PermissionDto;
import pwc.taxtech.atms.dto.role.RoleDisplayDto;
import pwc.taxtech.atms.dto.role.RoleDto;
import pwc.taxtech.atms.dto.role.RoleDtoBase;
import pwc.taxtech.atms.dto.role.RoleDtoTree;
import pwc.taxtech.atms.dto.role.RolePermissionDto;
import pwc.taxtech.atms.dto.role.UpdateRoleInfo;
import pwc.taxtech.atms.dto.user.*;
import pwc.taxtech.atms.entity.*;
import pwc.taxtech.atms.entity.UserRoleExample.Criteria;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.toList;

@Service
public class RoleServiceImpl extends AbstractService {

    @Autowired
    private UserServiceImpl userService;

    @Autowired
    private UserRoleServiceImpl userRoleService;

    @Autowired
    private OrganizationServiceImpl organizationService;

    public List<NavTreeDto> getRoleTreeList() {
        logger.debug("RoleServiceImpl getRoleTreeList");
        RoleCategoryExample roleCategoryExample = new RoleCategoryExample();
        roleCategoryExample.createCriteria().andIsActiveEqualTo(CommonConstants.ACTIVE_STATUS);
        List<RoleCategory> roleCategoryList = roleCategoryMapper.selectByExample(roleCategoryExample);
        List<Role> allRoleList = roleMapper.selectByExample(new RoleExample());
        List<NavTreeDto> retList = new ArrayList<>();
        for (RoleCategory category : roleCategoryList) {
            NavTreeDto treeDto = new NavTreeDto();
            RoleCategoryDto roleCategoryDto = new RoleCategoryDto();
            CommonUtils.copyProperties(category, roleCategoryDto);
            treeDto.setChildren(new ArrayList<>());
            treeDto.setData(roleCategoryDto);
            treeDto.setLabel(category.getName());
            List<NavTreeDto> treeDtoChildren = new ArrayList<>();

            List<Role> roleList = allRoleList.stream()
                    .filter(oneRole -> oneRole.getRoleCategoryId().equals(category.getId()))
                    .collect(Collectors.toList());
            for (Role role : roleList) {
                NavTreeDto roleTreeDto = new NavTreeDto();
                roleTreeDto.setChildren(new ArrayList<>());
                roleTreeDto.setLabel(role.getName());
                roleTreeDto.setData(role);
                treeDtoChildren.add(roleTreeDto);
            }
            treeDto.setChildren(treeDtoChildren);
            retList.add(treeDto);
        }
        return retList;
    }

    public List<UserRoleInfo> getUserRoleByUser(VMUser vmUser) {
        List<VMUser> list = new ArrayList<>();
        list.add(vmUser);
        return getAllUserRoleListByUserList(list, "");
    }

    private List<UserRoleInfo> getAllUserRoleListByUserList(List<VMUser> userList, String dimensionValueId) {
        List<Role> roles = findAll();
        // 角色列表
        List<NameDto> roleList = roles.stream().map(this::rotateRoleToNameDto).collect(Collectors.toList());

        // 获取原始角色列表
        List<UserRoleSimpleDto> userRoleList = getOriginalUserRoleList(roleList);

        // 用户维度
        List<UserDimensionValue> userDimensionValueList = findAllUserDimensionValue();

        // 不继承的维度列表
        List<UserDimensionValueOrg> notuserDimensionValueOrg = findUserDimensionValueOrgByIsHeritable(
                CommonConstants.IsNotHeritable);

        // 维度角色列表
        List<UserDimensionValueRoleDto> dimensionValueRoleList = getDimensionValueRoleList(roleList);

        // 用户机构
        List<UserOrganization> userOrganizationList = findAllUserOrganization();

        // 机构角色列表
        List<UserOrganizationRoleDto> userOrganizationRoleList = getUserOrganizationRoleList(roleList);

        // 机构列表
        List<Organization> organizations = findAllOrganization();
        List<OrganizationDto> organizationList = organizations.stream().map(this::rotateOrganizationToOrganizationDto)
                .collect(Collectors.toList());

        // 机构维度设置列表
        List<DimensionValueOrgDto> dimensionValueOrgList = getDimensionValueOrgDtoList();

        if (StringUtils.hasText(dimensionValueId)) {
            // 只要某个维度值下面的机构
            List<OrganizationDto> organizationDtos = new ArrayList<>();
            for (DimensionValueOrgDto dimensionValueOrgDto : dimensionValueOrgList) {
                if (!dimensionValueId.equals(dimensionValueOrgDto.getDimensionValueId())) {
                    continue;
                }
                for (OrganizationDto organizationDto : organizationList) {
                    if (organizationDto.getId().equals(dimensionValueOrgDto.getOrganizationId())) {
                        organizationDtos.add(organizationDto);
                    }
                }
            }
            organizationList = organizationDtos;
        }

        List<UserRoleInfo> retList = new ArrayList<>();
        for (OrganizationDto orgInfo : organizationList) {
            List<UserOrganization> thisUserOrganizationList = userOrganizationList.stream()
                    .filter(oneUserOrganization -> orgInfo.getId().equals(oneUserOrganization.getOrganizationId()))
                    .collect(Collectors.toList());
            List<DimensionValueOrgDto> thisDimensionValueOrgList = dimensionValueOrgList.stream()
                    .filter(oneDimension -> orgInfo.getId().equals(oneDimension.getOrganizationId()))
                    .collect(Collectors.toList());
            // 用户维度关联表,排除不继承的关联
            List<UserDimensionValue> thisUserDimensionValueList = new ArrayList<>();
            for (UserDimensionValue userDimensionValue : userDimensionValueList) {
                if (!notuserDimensionValueOrg.stream()
                        .anyMatch(oneDimension -> orgInfo.getId().equals(oneDimension.getOrganizationId())
                                && userDimensionValue.getId().equals(oneDimension.getUserDimensionValueId()))) {
                    thisUserDimensionValueList.add(userDimensionValue);
                }
            }
            List<UserRoleInfo> orgUserInfoList = getUserRoleInfoListByOrg(thisUserOrganizationList, orgInfo, userList,
                    userRoleList, thisUserDimensionValueList, thisDimensionValueOrgList, userOrganizationRoleList,
                    dimensionValueRoleList);
            if (!orgUserInfoList.isEmpty()) {
                retList.addAll(orgUserInfoList);
            }
        }
        return retList;
    }

    private List<Role> findAll() {
        RoleExample roleExample = new RoleExample();
        return roleMapper.selectByExample(roleExample);
    }

    private List<UserRole> findAllUserRoles() {
        UserRoleExample userRoleExample = new UserRoleExample();
        return userRoleMapper.selectByExample(userRoleExample);
    }

    private List<UserDimensionValue> findAllUserDimensionValue() {
        UserDimensionValueExample userDimensionValueExample = new UserDimensionValueExample();
        return userDimensionValueMapper.selectByExample(userDimensionValueExample);
    }

    private List<UserDimensionValueOrg> findUserDimensionValueOrgByIsHeritable(Boolean isHeritable) {
        UserDimensionValueOrgExample userDimensionValueOrgExample = new UserDimensionValueOrgExample();
        userDimensionValueOrgExample.createCriteria().andIsHeritableEqualTo(isHeritable);
        return userDimensionValueOrgMapper.selectByExample(userDimensionValueOrgExample);
    }

    private List<UserDimensionValueRole> findAllUserDimensionValueRole() {
        UserDimensionValueRoleExample userDimensionValueRoleExample = new UserDimensionValueRoleExample();
        return userDimensionValueRoleMapper.selectByExample(userDimensionValueRoleExample);
    }

    private List<UserOrganizationRole> findAllUserOrganizationRole() {
        UserOrganizationRoleExample userOrganizationRoleExample = new UserOrganizationRoleExample();
        return userOrganizationRoleMapper.selectByExample(userOrganizationRoleExample);
    }

    private List<UserOrganization> findAllUserOrganization() {
        UserOrganizationExample userOrganizationExample = new UserOrganizationExample();
        return userOrganizationMapper.selectByExample(userOrganizationExample);
    }

    private List<Organization> findAllOrganization() {
        OrganizationExample organizationExample = new OrganizationExample();
        return organizationMapper.selectByExample(organizationExample);
    }

    private NameDto rotateRoleToNameDto(Role role) {
        NameDto nameDto = new NameDto();
        CommonUtils.copyProperties(role, nameDto);
        return nameDto;
    }

    private List<UserRoleSimpleDto> getOriginalUserRoleList(List<NameDto> roleList) {
        List<UserRole> userRoles = findAllUserRoles();

        List<UserRoleSimpleDto> userRoleList = new ArrayList<>();
        for (NameDto nameDto : roleList) {
            for (UserRole userRole : userRoles) {
                if (nameDto.getId().equals(userRole.getRoleId())) {
                    userRoleList.add(rotateUserRoleToUserRoleSimpleDto(userRole, nameDto.getName()));
                }
            }
        }
        return userRoleList;
    }

    private List<UserDimensionValueRoleDto> getDimensionValueRoleList(List<NameDto> roleList) {
        List<UserDimensionValueRole> userDimensionValueRoles = findAllUserDimensionValueRole();
        List<UserDimensionValueRoleDto> dimensionValueRoleList = new ArrayList<>();
        for (NameDto nameDto : roleList) {
            for (UserDimensionValueRole userDimensionValueRole : userDimensionValueRoles) {
                if (nameDto.getId().equals(userDimensionValueRole.getRoleId())) {
                    dimensionValueRoleList.add(rotateUserDimensionValueRoleToUserDimensionValueRoleDto(
                            userDimensionValueRole, nameDto.getName()));
                }
            }
        }
        return dimensionValueRoleList;
    }

    private UserRoleSimpleDto rotateUserRoleToUserRoleSimpleDto(UserRole userRole, String name) {
        UserRoleSimpleDto userRoleSimpleDto = new UserRoleSimpleDto();
        userRoleSimpleDto.setId(userRole.getId());
        userRoleSimpleDto.setRoleId(userRole.getRoleId());
        userRoleSimpleDto.setRoleName(name);
        userRoleSimpleDto.setUserId(userRole.getUserId());
        return userRoleSimpleDto;
    }

    private UserDimensionValueRoleDto rotateUserDimensionValueRoleToUserDimensionValueRoleDto(
            UserDimensionValueRole userDimensionValueRole, String name) {
        UserDimensionValueRoleDto userDimensionValueRoleDto = new UserDimensionValueRoleDto();
        userDimensionValueRoleDto.setId(userDimensionValueRole.getId());
        userDimensionValueRoleDto.setRoleId(userDimensionValueRole.getRoleId());
        userDimensionValueRoleDto.setRoleName(name);
        userDimensionValueRoleDto.setUserDimensionValueId(userDimensionValueRole.getUserDimensionValueId());
        return userDimensionValueRoleDto;
    }

    private UserOrganizationRoleDto rotateUserOrganizationRoleToUserOrganizationRoleDto(
            UserOrganizationRole userOrganizationRole, String name) {
        UserOrganizationRoleDto userOrganizationRoleDto = new UserOrganizationRoleDto();
        CommonUtils.copyProperties(userOrganizationRole, userOrganizationRoleDto);
        userOrganizationRoleDto.setRoleName(name);
        return userOrganizationRoleDto;
    }

    private OrganizationDto rotateOrganizationToOrganizationDto(Organization organization) {
        OrganizationDto organizationDto = new OrganizationDto();
        CommonUtils.copyProperties(organization, organizationDto);
        return organizationDto;
    }

    private RoleInfo rotateUserSimpleRoleDtoToRoleInfo(UserRoleSimpleDto userRoleSimpleDto) {
        RoleInfo roleInfo = new RoleInfo();
        roleInfo.setId(userRoleSimpleDto.getRoleId());
        roleInfo.setName(userRoleSimpleDto.getRoleName());
        return roleInfo;
    }

    private RoleInfo rotateUserDimensionValueRoleDtoToRoleInfo(UserDimensionValueRoleDto userDimensionValueRoleDto) {
        RoleInfo roleInfo = new RoleInfo();
        roleInfo.setId(userDimensionValueRoleDto.getRoleId());
        roleInfo.setName(userDimensionValueRoleDto.getRoleName());
        return roleInfo;
    }

    private RoleInfo rotateUserOrganizationRoleDtoToRoleInfo(UserOrganizationRoleDto userOrganizationRoleDto) {
        RoleInfo roleInfo = new RoleInfo();
        roleInfo.setId(userOrganizationRoleDto.getRoleId());
        roleInfo.setName(userOrganizationRoleDto.getRoleName());
        return roleInfo;
    }

    private List<UserOrganizationRoleDto> getUserOrganizationRoleList(List<NameDto> roleList) {
        List<UserOrganizationRole> userOrganizationRoles = findAllUserOrganizationRole();
        List<UserOrganizationRoleDto> userOrganizationRoleList = new ArrayList<>();
        for (NameDto nameDto : roleList) {
            for (UserOrganizationRole userOrganizationRole : userOrganizationRoles) {
                if (nameDto.getId().equals(userOrganizationRole.getRoleId())) {
                    userOrganizationRoleList.add(rotateUserOrganizationRoleToUserOrganizationRoleDto(
                            userOrganizationRole, nameDto.getName()));
                }
            }
        }
        return userOrganizationRoleList;
    }

    private List<DimensionValueOrgDto> getDimensionValueOrgDtoList() {
        DimensionParamDto dimensionParamDto = new DimensionParamDto();
        dimensionParamDto.setOrganizationStructureId(DimensionConstant.OrganizationStructureId);
        dimensionParamDto.setBusinessUnitId(DimensionConstant.BusinessUnitId);
        dimensionParamDto.setAreaId(DimensionConstant.AreaId);
        List<UnionDimensionValueOrg> unionDimensionValueOrgs = dimensionValueOrgMapper
                .selectUnionDimensionValueOrgByDimension(dimensionParamDto);
        return unionDimensionValueOrgs.stream().map(this::rotateUnionDimensionValueOrgToDimensionValueOrgDto)
                .collect(Collectors.toList());
    }

    private DimensionValueOrgDto rotateUnionDimensionValueOrgToDimensionValueOrgDto(
            UnionDimensionValueOrg unionDimensionValueOrg) {
        DimensionValueOrgDto dimensionValueOrgDto = new DimensionValueOrgDto();
        CommonUtils.copyProperties(unionDimensionValueOrg, dimensionValueOrgDto);
        dimensionValueOrgDto.setDimensionName("");
        return dimensionValueOrgDto;
    }

    private List<UserRoleInfo> getUserRoleInfoListByOrg(List<UserOrganization> userOrganizationList,
                                                        OrganizationDto orgInfo, List<VMUser> userList, List<UserRoleSimpleDto> userRoleList,
                                                        List<UserDimensionValue> userDimensionValueList, List<DimensionValueOrgDto> dimensionValueOrgList,
                                                        List<UserOrganizationRoleDto> userOrganizationRoleList,
                                                        List<UserDimensionValueRoleDto> dimensionValueRoleList) {
        List<UserRoleInfo> retList = new ArrayList<>();
        List<UserOrganization> thisUserOrganizationList = userOrganizationList;
        // 机构在维度上的设置
        List<UserDimensionValue> userDimensionValues = new ArrayList<>();
        for (UserDimensionValue userDimensionValue : userDimensionValueList) {
            if (userDimensionValue.getDimensionValueId() == null) {
                continue;
            }
            for (DimensionValueOrgDto dimensionValueOrgDto : dimensionValueOrgList) {
                if (userDimensionValue.getDimensionValueId().equals(dimensionValueOrgDto.getDimensionValueId())) {
                    userDimensionValues.add(userDimensionValue);
                }
            }
        }
        userDimensionValueList = userDimensionValues;
        List<String> notAccessUserList = new ArrayList<>();

        // 1 机构上设置了,维度上也设置了
        for (UserOrganization userOrganization : thisUserOrganizationList) {
            List<VMUser> users = userList.stream()
                    .filter(oneUser -> oneUser.getId().equals(userOrganization.getUserId()))
                    .collect(Collectors.toList());
            if (users.isEmpty()) {
                continue;
            }
            VMUser user = users.get(0);
            // 不可继承的只需要附加角色
            UserRoleInfo oneUserRoleModel = new UserRoleInfo();
            oneUserRoleModel.setId(userOrganization.getUserId());
            oneUserRoleModel.setOrganizationId(orgInfo.getId());
            oneUserRoleModel.setOrganizationName(orgInfo.getName());
            oneUserRoleModel.setRoleInfoList(new ArrayList<>());
            oneUserRoleModel.setIsAccessible(CommonConstants.IsAccessible.equals(userOrganization.getIsAccessible()));
            oneUserRoleModel.setStatus(user.getStatus());
            oneUserRoleModel.setUserName(user.getUserName());
            oneUserRoleModel.setServiceTypeId("");
            oneUserRoleModel.setAreaId(orgInfo.getAreaId());
            oneUserRoleModel.setBusinessUnitId(orgInfo.getBusinessUnitId());

            if (CommonConstants.IsNotAccessible.equals(userOrganization.getIsAccessible())) {
                notAccessUserList.add(user.getUserName());
                continue;
            }
            if (oneUserRoleModel.getIsAccessible()) {
                // 机构在维度上的设置
                List<UserDimensionValue> thisUserDimensionValueList = userDimensionValueList.stream()
                        .filter(oneUserDiemension -> oneUserDiemension.getUserId() != null
                                && oneUserDiemension.getUserId().equals(userOrganization.getUserId()))
                        .collect(Collectors.toList());
                // 任意一个维度不可访问都不可访问
                if (thisUserDimensionValueList.stream().anyMatch(oneUserDiemension -> CommonConstants.IsNotAccessible
                        .equals(oneUserDiemension.getIsAccessible()))) {
                    continue;
                }
                if (CommonConstants.HasOriginalRole.equals(userOrganization.getHasOriginalRole())
                        || thisUserDimensionValueList.stream().anyMatch(
                        oneValue -> CommonConstants.HasOriginalRole.equals(oneValue.getHasOriginalRole()))) {
                    // 原始角色
                    List<RoleInfo> origianlRoleList = userRoleList.stream()
                            .filter(oneUserRole -> oneUserRole.getUserId() != null
                                    && oneUserRole.getUserId().equals(userOrganization.getUserId()))
                            .map(this::rotateUserSimpleRoleDtoToRoleInfo).distinct().collect(Collectors.toList());
                    if (!origianlRoleList.isEmpty()) {
                        oneUserRoleModel.setRoleInfoList(origianlRoleList);
                    }
                }

                List<RoleInfo> dimensionRoleList = new ArrayList<>();
                for (UserDimensionValueRoleDto userDimensionValueRoleDto : dimensionValueRoleList) {
                    if (oneUserRoleModel.getRoleInfoList() == null || oneUserRoleModel.getRoleInfoList().stream()
                            .anyMatch(oneRole -> oneRole.getId().equals(userDimensionValueRoleDto.getRoleId()))) {
                        continue;
                    }
                    for (UserDimensionValue userDimensionValue : thisUserDimensionValueList) {
                        if (userDimensionValue.getId().equals(userDimensionValueRoleDto.getUserDimensionValueId())) {
                            dimensionRoleList.add(rotateUserDimensionValueRoleDtoToRoleInfo(userDimensionValueRoleDto));
                        }
                    }
                }

                dimensionRoleList = dimensionRoleList.stream().distinct().collect(Collectors.toList());
                oneUserRoleModel.getRoleInfoList().addAll(dimensionRoleList);

                List<RoleInfo> userOrgRoleList = userOrganizationRoleList.stream()
                        .filter(p -> userOrganization.getId().equals(p.getUserOrganizationId()) && !oneUserRoleModel
                                .getRoleInfoList().stream().anyMatch(sa -> sa.getId().equals(p.getRoleId())))
                        .map(this::rotateUserOrganizationRoleDtoToRoleInfo).collect(Collectors.toList());
                oneUserRoleModel.getRoleInfoList().addAll(userOrgRoleList);

                if (oneUserRoleModel.getRoleInfoList().isEmpty()) {
                    continue;
                }
            } else {
                // 不可访问不显示
                continue;
            }
            retList.add(oneUserRoleModel);
        }

        // 2 机构上没有设置 维度上设置了
        List<UserDimensionValue> dimensionOnlyList = userDimensionValueList.stream()
                .filter(p -> !retList.stream().anyMatch(sa -> sa.getId().equals(p.getUserId())))
                .collect(Collectors.toList());
        List<String> distinctUserId = dimensionOnlyList.stream().map(sa -> sa.getUserId()).distinct()
                .collect(Collectors.toList());
        for (String userId : distinctUserId) {
            List<VMUser> users = userList.stream().filter(sa -> sa.getId().equals(userId)).collect(Collectors.toList());
            if (users.isEmpty()) {
                continue;
            }
            VMUser user = users.get(0);

            // 机构上面设置过不可访问的
            if (notAccessUserList.stream().anyMatch(sa -> sa.equals(user.getUserName()))) {
                continue;
            }

            List<UserDimensionValue> userDimensionTempList = dimensionOnlyList.stream()
                    .filter(sa -> sa.getUserId().equals(userId)).collect(Collectors.toList());
            if (userDimensionTempList.isEmpty() || userDimensionTempList.stream()
                    .anyMatch(sa -> CommonConstants.IsNotAccessible.equals(sa.getIsAccessible()))) {
                continue;
            }
            UserRoleInfo oneUserRoleModel = new UserRoleInfo();
            oneUserRoleModel.setId(user.getId());
            oneUserRoleModel.setOrganizationId(orgInfo.getId());
            oneUserRoleModel.setOrganizationName(orgInfo.getName());
            oneUserRoleModel.setRoleInfoList(new ArrayList<>());
            oneUserRoleModel.setIsAccessible(true);
            oneUserRoleModel.setStatus(user.getStatus());
            oneUserRoleModel.setEmail(user.getEmail());
            oneUserRoleModel.setUserName(user.getUserName());
            oneUserRoleModel.setServiceTypeId("");
            oneUserRoleModel.setAreaId(orgInfo.getAreaId());
            oneUserRoleModel.setBusinessUnitId(orgInfo.getBusinessUnitId());

            // 机构在维度上的设置
            List<UserDimensionValue> thisUserDimensionValueList = new ArrayList<>();
            for (UserDimensionValue userDimensionValue : userDimensionTempList) {
                if (userDimensionValue.getDimensionValueId() == null
                        || !userId.equals(userDimensionValue.getUserId())) {
                    continue;
                }
                for (DimensionValueOrgDto dimensionValueOrgDto : dimensionValueOrgList) {
                    if (userDimensionValue.getDimensionValueId().equals(dimensionValueOrgDto.getDimensionValueId())) {
                        thisUserDimensionValueList.add(userDimensionValue);
                    }
                }
            }

            // 任意一个维度不可访问都不可访问
            if (thisUserDimensionValueList.stream()
                    .anyMatch(sa -> CommonConstants.IsNotAccessible.equals(sa.getIsAccessible()))) {
                continue;
            }

            if (thisUserDimensionValueList.stream()
                    .anyMatch(sa -> CommonConstants.HasOriginalRole.equals(sa.getHasOriginalRole()))) {
                // 原始角色
                List<RoleInfo> origianlRoleList = userRoleList.stream().filter(p -> userId.equals(p.getUserId()))
                        .map(this::rotateUserSimpleRoleDtoToRoleInfo).distinct().collect(Collectors.toList());
                if (!origianlRoleList.isEmpty()) {
                    oneUserRoleModel.setRoleInfoList(origianlRoleList);
                }
            }

            List<RoleInfo> dimensionRoleList = new ArrayList<>();
            for (UserDimensionValueRoleDto userDimensionValueRoleDto : dimensionValueRoleList) {
                if (userDimensionValueRoleDto.getUserDimensionValueId() == null || oneUserRoleModel.getRoleInfoList()
                        .stream().anyMatch(sa -> sa.getId().equals(userDimensionValueRoleDto.getRoleId()))) {
                    continue;
                }
                for (UserDimensionValue userDimensionValue : thisUserDimensionValueList) {
                    if (userDimensionValueRoleDto.getUserDimensionValueId().equals(userDimensionValue.getId())) {
                        dimensionRoleList.add(rotateUserDimensionValueRoleDtoToRoleInfo(userDimensionValueRoleDto));
                    }
                }
            }
            dimensionRoleList = dimensionRoleList.stream().distinct().collect(Collectors.toList());

            oneUserRoleModel.getRoleInfoList().addAll(dimensionRoleList);
            retList.add(oneUserRoleModel);
        }
        return retList;
    }

    public List<UserRoleInfo> getAllOwnUserRoleList() {
        logger.debug("Start to get all own user roles");
        List<User> userList = userService.findAllUsers();
        // 角色列表
        List<Role> roleList = findAll();
        // 原始维度
        List<UserRole> userRoleList = userRoleService.findAllUserRoles();
        List<Organization> organizationList = organizationService.findAllOrganizations();
        List<UserRoleInfo> retList = new ArrayList<>();

        for (User userItem : userList) {
            List<UserRole> sameList = userRoleList.stream().filter(sa -> userItem.getId().equals(sa.getUserId()))
                    .collect(Collectors.toList());
            List<Organization> orgList = organizationList.stream()
                    .filter(sa -> sa.getId().equals(userItem.getOrganizationId())).collect(Collectors.toList());
            if (orgList.isEmpty()) {
                continue;
            }
            Organization org = orgList.get(0);
            UserRoleInfo userRoleInfo = new UserRoleInfo();
            userRoleInfo.setUserName(userItem.getUserName());
            userRoleInfo.setStatus(userItem.getStatus());
            userRoleInfo.setServiceTypeId("");
            userRoleInfo.setRoleInfoList(new ArrayList<>());
            userRoleInfo.setOrganizationName(org.getName());
            userRoleInfo.setOrganizationId(org.getId());
            userRoleInfo.setIsAccessible(true);
            userRoleInfo.setEmail(userItem.getEmail());
            userRoleInfo.setBusinessUnitId(org.getBusinessUnitId());
            userRoleInfo.setAreaId(org.getAreaId());
            userRoleInfo.setId(userItem.getId());

            List<RoleInfo> roleInfoList = new ArrayList<>();
            for (UserRole userRole : sameList) {
                for (Role role : roleList) {
                    if (role.getId().equals(userRole.getRoleId())) {
                        RoleInfo roleInfo = new RoleInfo();
                        roleInfo.setDimensionId("");
                        roleInfo.setDimensionValue("");
                        roleInfo.setDimensionValueId("");
                        roleInfo.setId(role.getId());
                        roleInfo.setIsAccessible(true);
                        roleInfo.setIsHeritable(true);
                        roleInfo.setName(role.getName());
                        roleInfo.setRoleSource(RoleSourceEnum.OriginalLevel.value());
                        roleInfoList.add(roleInfo);
                    }
                }
            }
            userRoleInfo.setRoleInfoList(roleInfoList);
            retList.add(userRoleInfo);
        }
        return retList;
    }

    public List<UserRoleInfo> getAllUserRoleList() {
        List<VMUser> userList = userService.findAllUsers().stream().map(this::rotateUserToVMUser)
                .collect(Collectors.toList());
        return getAllUserRoleListByUserList(userList, "");
    }

    private VMUser rotateUserToVMUser(User user) {
        VMUser vmUser = new VMUser();
        CommonUtils.copyProperties(user, vmUser);
        return vmUser;
    }

    public List<UserRoleDto> getAllRoleListByUserId(String userId, String serviceTypeId) {
        UserRoleExample userRoleExample = new UserRoleExample();
        Criteria criteria = userRoleExample.createCriteria();
        criteria.andUserIdEqualTo(userId);
        criteria.andServiceTypeIdEqualTo(serviceTypeId);
        List<UserRole> userRoles = userRoleMapper.selectByExample(userRoleExample);

        List<UserRoleDto> roleList = new ArrayList<>();
        if (userRoles == null || userRoles.isEmpty()) {
            return roleList;
        }
        List<Map<String, String>> userRoleList = userRoles.stream().map(this::convertUserRoleToMap).distinct()
                .collect(Collectors.toList());

        for (Map<String, String> l : userRoleList) {
            Role role = roleMapper.selectByPrimaryKey(l.get("roleId"));
            UserRoleDto userRoleDto = new UserRoleDto();
            userRoleDto.setRoleId(l.get("roleId"));
            userRoleDto.setUserId(l.get("userId"));
            userRoleDto.setRoleName(role == null ? "" : role.getName());
            roleList.add(userRoleDto);
        }
        return roleList;
    }

    private Map<String, String> convertUserRoleToMap(UserRole userRole) {
        Map<String, String> map = new HashMap<>();
        map.put("roleId", userRole.getRoleId());
        map.put("userId", userRole.getUserId());
        return map;
    }

    /**
     * 事业部,获取用户数统计,包括维度上的和机构上的(统计可访问,不管有无角色)
     */
    public List<UserOrgDto> getUserByDimensionValue(List<OrganizationDto> orgList,
                                                    List<UserDimensionValue> userDimensionValueList, List<UserDimensionValueOrg> userDimensionValueOrgList,
                                                    List<UserOrganization> userOrganizationList, List<UserOrgRoleDto> originalRoleList,
                                                    List<UserOrgRoleDto> userDimensionValueRoleList, List<UserOrgRoleDto> userOrganizationRoleList,
                                                    String dimensionId, String dimensionValueId) {
        List<UserOrgDto> userOrgDtoList = new ArrayList<>();
        // 去掉没有机构的数据
        orgList = orgList.stream().filter(s -> StringUtils.hasText(s.getId())).collect(Collectors.toList());

        List<UserRoleDimensionValueDto> dimensionOrgList = new ArrayList<>();
        for (OrganizationDto p : orgList) {
            for (UserDimensionValue q : userDimensionValueList) {
                if (Objects.equals(p.getDimensionId(), q.getDimensionId())
                        && Objects.equals(p.getDimensionValueId(), q.getDimensionValueId())) {
                    UserRoleDimensionValueDto uo = new UserRoleDimensionValueDto();
                    uo.setUserId(q.getUserId());
                    uo.setOrganizationId(p.getId());
                    uo.setOrganizationName(p.getName());
                    uo.setDimensionId(q.getDimensionId());
                    uo.setDimensionValueId(q.getDimensionValueId());
                    uo.setIsAccessible(BooleanUtils.isTrue(q.getIsAccessible()));
                    uo.setHasOriginalRole(BooleanUtils.isTrue(q.getHasOriginalRole()));
                    uo.setId(q.getId());
                    dimensionOrgList.add(uo);
                }
            }
        }

        List<UserOrgRoleDto> originalRole = new ArrayList<>();
        List<UserOrgRoleDto> extraDimensionRoleList = new ArrayList<>();
        List<UserOrgDto> orgNoAccessList = new ArrayList<>();

        // 维度上的机构的用户
        for (UserRoleDimensionValueDto g : dimensionOrgList) {
            // 机构在维度上是否可以被继承,或者被访问
            UserDimensionValueOrg userDimensionValuerOrg = userDimensionValueOrgList.stream()
                    .filter(uvg -> Objects.equals(uvg.getUserDimensionValueId(), g.getId())
                            && Objects.equals(uvg.getOrganizationId(), g.getOrganizationId()))
                    .findFirst().orElse(null);

            // 如果没有设置值,默认可以继承
            boolean isHeritable = userDimensionValuerOrg == null
                    || BooleanUtils.isTrue(userDimensionValuerOrg.getIsHeritable());
            if (!isHeritable) {
                continue;
            }

            // 用户继承了不可访问的,则这个机构不可访问
            if (isHeritable && !BooleanUtils.isTrue(g.getIsAccessible())
                    && !orgNoAccessList.stream().anyMatch(s -> Objects.equals(s.getOrgId(), g.getOrganizationId())
                    && Objects.equals(s.getUserId(), g.getUserId()))) {
                UserOrgDto orgRoleInfo = new UserOrgDto();
                orgRoleInfo.setOrgId(g.getOrganizationId());
                orgRoleInfo.setUserId(g.getUserId());
                orgNoAccessList.add(orgRoleInfo);

                continue;
            }
            originalRole.clear();
            extraDimensionRoleList.clear();
            if (isHeritable && BooleanUtils.isTrue(g.getHasOriginalRole())) {
                originalRole = originalRoleList.stream().filter(s -> Objects.equals(s.getUserId(), g.getUserId()))
                        .collect(Collectors.toList());
            }
            if (originalRole.isEmpty()) {
                extraDimensionRoleList = userDimensionValueRoleList.stream()
                        .filter(s -> Objects.equals(s.getId(), g.getId())).collect(Collectors.toList());
            }
            // 有角色才添加
            if (!originalRole.isEmpty() || !extraDimensionRoleList.isEmpty()
                    && !userOrgDtoList.stream().anyMatch(s -> Objects.equals(s.getUserId(), g.getUserId())
                    && Objects.equals(s.getOrgId(), g.getOrganizationId()))) {
                UserOrgDto userOrgDto = new UserOrgDto();
                userOrgDto.setUserId(g.getUserId());
                userOrgDto.setOrgId(g.getOrganizationId());
                userOrgDtoList.add(userOrgDto);
            }
        }
        // 移除没有访问权限的维度上的机构
        userOrgDtoList = userOrgDtoList.stream().filter(q -> !orgNoAccessList.stream().anyMatch(
                es -> Objects.equals(es.getOrgId(), q.getOrgId()) && Objects.equals(es.getUserId(), q.getUserId())))
                .collect(Collectors.toList());

        // 机构上的用户
        List<UserRoleDimensionValueDto> userOrgList = new ArrayList<>();
        for (OrganizationDto p : orgList) {
            if (p == null) {
                continue;
            }
            for (UserOrganization q : userOrganizationList) {
                if (Objects.equals(p.getId(), q.getOrganizationId())
                        && !orgNoAccessList.stream().anyMatch(es -> Objects.equals(es.getOrgId(), p.getId())
                        && Objects.equals(es.getUserId(), q.getUserId()))) {
                    UserRoleDimensionValueDto uo = new UserRoleDimensionValueDto();
                    uo.setUserId(q.getUserId());
                    uo.setOrganizationId(p.getId());
                    uo.setOrganizationName(p.getName());
                    uo.setId(q.getId());
                    uo.setIsAccessible(BooleanUtils.isTrue(q.getIsAccessible()));
                    uo.setHasOriginalRole(BooleanUtils.isTrue(q.getHasOriginalRole()));
                    userOrgList.add(uo);
                }
            }
        }

        for (UserRoleDimensionValueDto orgDto : userOrgList) {
            originalRole.clear();
            extraDimensionRoleList.clear();
            if (BooleanUtils.isTrue(orgDto.getHasOriginalRole())) {
                originalRole = originalRoleList.stream().filter(s -> Objects.equals(s.getUserId(), orgDto.getUserId()))
                        .collect(Collectors.toList());
            }
            if (originalRole.isEmpty()) {
                extraDimensionRoleList = userOrganizationRoleList.stream()
                        .filter(s -> Objects.equals(s.getId(), orgDto.getId())).collect(Collectors.toList());
            }
            if (!originalRole.isEmpty() || !extraDimensionRoleList.isEmpty()
                    && !userOrgDtoList.stream().anyMatch(s -> Objects.equals(s.getUserId(), orgDto.getUserId())
                    && Objects.equals(s.getOrgId(), orgDto.getOrganizationId()))) {
                UserOrgDto userOrgDto = new UserOrgDto();
                userOrgDto.setUserId(orgDto.getUserId());
                userOrgDto.setOrgId(orgDto.getOrganizationId());
                userOrgDtoList.add(userOrgDto);
            }
        }

        return userOrgDtoList;
    }

    public List<RoleDtoTree> getRoleList() {
        Integer serviceType = ServiceTypeEnum.VAT.value();

        List<RoleDtoTree> roleTree = new ArrayList<>();
        List<RoleCategory> roleCategoryList = findRoleCategoryByIsActiveOrderByCreateTime(
                CommonConstants.ACTIVE_STATUS);
        List<Role> roleList = findAll();
        for (RoleCategory rc : roleCategoryList) {
            RoleDtoTree tree = null;
            if (roleList != null && !roleList.isEmpty()) {
                List<RoleDtoBase> roles = roleList.stream()
                        .filter(r -> serviceType.toString().equals(r.getServiceTypeId())
                                && r.getRoleCategoryId() != null && r.getRoleCategoryId().equals(rc.getId()))
                        .map(x -> CommonUtils.copyProperties(x, new RoleDtoBase())).collect(Collectors.toList());
                tree = wrapperRole(roles, rc);
            } else {
                tree = wrapperRole(null, rc);
            }
            roleTree.add(tree);
        }
        return roleTree;
    }

    private List<RoleCategory> findRoleCategoryByIsActiveOrderByCreateTime(Boolean isActive) {
        RoleCategoryExample roleCategoryExample = new RoleCategoryExample();
        roleCategoryExample.createCriteria().andIsActiveEqualTo(isActive);
        roleCategoryExample.setOrderByClause("CREATE_TIME ASC");
        return roleCategoryMapper.selectByExample(roleCategoryExample);
    }

    private RoleDtoTree wrapperRole(List<RoleDtoBase> roles, RoleCategory rt) {
        RoleDtoTree one = new RoleDtoTree();
        one.setId(rt.getId());
        one.setName(rt.getName());
        one.setRoleCategoryId(rt.getId());
        one.setIsRoleCategory(true);

        if (roles != null) {
            for (RoleDtoBase item : roles) {
                item.setRoleCategoryId(rt.getId());
                item.setIsRoleCategory(false);
            }
        }
        one.setSubRoles(roles);
        return one;
    }

    /*
     * (non-Javadoc)
     *
     * @see pwc.taxtech.atms.service.RoleService#getUsersByRoleId(java.lang.String)
     */
    public List<UserRoleDto> getUsersByRoleId(String roleId) {

        ServiceTypeEnum serviceType = ServiceTypeEnum.VAT;
        UserRoleExample userRoleExample = new UserRoleExample();
        userRoleExample.createCriteria().andServiceTypeIdEqualTo(serviceType.value().toString())
                .andRoleIdEqualTo(roleId);
        List<UserRole> userRoleList = userRoleMapper.selectByExample(userRoleExample);

        List<UserRoleDto> userRoleDtoList = new ArrayList<>();
        userRoleList.stream().forEach(userRole -> {
            UserRoleDto userRoleDto = new UserRoleDto();
            userRoleDto.setUserId(userRole.getUserId());
            userRoleDto.setRoleId(userRole.getRoleId());
            userRoleDto.setServiceTypeId(userRole.getServiceTypeId());
            userRoleDtoList.add(userRoleDto);
        });

        List<UserRoleDto> userList = userRoleDtoList.stream().distinct().collect(Collectors.toList());

        for (UserRoleDto userRole : userList) {
            User user = userMapper.selectByPrimaryKey(userRole.getUserId());
            if (user != null) {
                userRole.setUserName(user.getUserName());
                if (user.getOrganizationId() != null && !user.getOrganizationId().isEmpty()) {
                    Organization organization = organizationMapper.selectByPrimaryKey(user.getOrganizationId());
                    userRole.setOrgId(user.getOrganizationId());
                    userRole.setOrgName(organization == null ? "" : organization.getName());
                }
            } else {
                userRole.setUserName("");
            }
        }
        return userList;
    }

    public Map<String, Integer> getActiveUserRoleList(List<OrganizationDto> orgList,
                                                      List<DimensionValueOrgDto> dimensionValueOrgList, String dimensionId) {
        UserExample userExample = new UserExample();
        userExample.createCriteria().andStatusNotEqualTo(0);
        List<VMUser> userList = userMapper.selectByExample(userExample).stream()
                .map(sa -> CommonUtils.copyProperties(sa, new VMUser())).collect(toList());
        // 获取原始角色列表
        List<UserRoleSimpleDto> userRoleList = userRoleMapper.selectByExample(new UserRoleExample()).stream()
                .map(p -> CommonUtils.copyProperties(p, new UserRoleSimpleDto())).collect(toList());
        // 用户维度
        UserDimensionValueExample userDimensionValueExample = new UserDimensionValueExample();
        userDimensionValueExample.createCriteria().andDimensionIdEqualTo(dimensionId);
        List<UserDimensionValue> userDimensionValueList = userDimensionValueMapper
                .selectByExample(userDimensionValueExample);
        // 不继承的维度列表
        UserDimensionValueOrgExample userDimensionValueOrgExample = new UserDimensionValueOrgExample();
        userDimensionValueOrgExample.createCriteria().andIsHeritableEqualTo(CommonConstants.IsNotHeritable);
        List<UserDimensionValueOrg> notuserDimensionValueOrg = userDimensionValueOrgMapper
                .selectByExample(userDimensionValueOrgExample);
        // 维度角色列表
        List<UserDimensionValueRoleDto> dimensionValueRoleList = userDimensionValueRoleMapper
                .selectByExample(new UserDimensionValueRoleExample()).stream()
                .map(p -> CommonUtils.copyProperties(p, new UserDimensionValueRoleDto())).collect(toList());
        // 用户机构
        List<UserOrganization> userOrganizationList = userOrganizationMapper
                .selectByExample(new UserOrganizationExample());
        // 机构角色列表
        List<UserOrganizationRoleDto> userOrganizationRoleList = userOrganizationRoleMapper
                .selectByExample(new UserOrganizationRoleExample()).stream()
                .map(p -> CommonUtils.copyProperties(p, new UserOrganizationRoleDto())).collect(toList());
        // 机构列表
        List<UserRoleInfo> retList = new ArrayList<>();
        for (OrganizationDto orgInfo : orgList) {
            List<UserOrganization> thisUserOrganizationList = userOrganizationList.stream()
                    .filter(sa -> Objects.equals(sa.getOrganizationId(), orgInfo.getId())).collect(toList());
            List<DimensionValueOrgDto> thisDimensionValueOrgList = dimensionValueOrgList.stream()
                    .filter(sa -> Objects.equals(sa.getOrganizationId(), orgInfo.getId())).collect(toList());
            // 用户维度关联表,排除不继承的关联
            List<UserDimensionValue> thisUserDimensionValueList = userDimensionValueList
                    .stream().filter(
                            p -> notuserDimensionValueOrg.stream()
                                    .noneMatch(sa -> Objects.equals(sa.getOrganizationId(), orgInfo.getId())
                                            && Objects.equals(sa.getUserDimensionValueId(), p.getId())))
                    .collect(toList());
            List<UserRoleInfo> orgUserInfoList = getUserRoleInfoListByOrg(thisUserOrganizationList, orgInfo, userList,
                    userRoleList, thisUserDimensionValueList, thisDimensionValueOrgList, userOrganizationRoleList,
                    dimensionValueRoleList);
            if (!orgUserInfoList.isEmpty()) {
                retList.addAll(orgUserInfoList);
            }
        }
        List<Map<String, String>> userResult = retList.stream().map(sa -> {
            Map<String, String> map = new HashMap<>();
            map.put("id", sa.getId());
            map.put("AreaId", sa.getAreaId());
            return map;
        }).distinct().collect(toList());
        List<String> areaIdList = userResult.stream().map(s -> s.get("AreaId")).distinct().collect(toList());
        Map<String, Integer> dic = new HashMap<>();
        for (String areaId : areaIdList) {
            Integer size = userResult.stream().filter(s -> Objects.equals(s.get("AreaId"), areaId)).collect(toList())
                    .size();
            dic.put(areaId == null ? CommonConstants.NullAreaId : areaId, size);
        }
        return dic;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * pwc.taxtech.atms.service.RoleService#getExtraUsersByRoleId(java.lang.String)
     */
    public List<UserRoleDto> getExtraUsersByRoleId(String roleId) {
        List<String> userRoleDimension = userDimensionValueRoleMapper.getUserIdByUserDimensionValueRole(roleId);

        List<String> userRoleOrginazation = userOrganizationRoleMapper.getUserIdByUserOrganizationRole(roleId);

        List<String> allUsers = new ArrayList<>();
        allUsers.addAll(userRoleDimension);
        allUsers.addAll(userRoleOrginazation);

        List<String> allUsersDistinct = allUsers.stream().distinct().collect(Collectors.toList());

        List<UserRoleDto> allExtraUsers = new ArrayList<>();
        for (String userId : allUsersDistinct) {
            if (userId == null || userId.isEmpty()) {
                continue;
            }
            UserRoleDto userRoleDto = new UserRoleDto();
            userRoleDto.setUserId(userId);
            userRoleDto.setRoleId(roleId);
            User user = userMapper.selectByPrimaryKey(userId);
            if (user != null) {
                userRoleDto.setUserName(user.getUserName());
                if (user.getOrganizationId() != null && !user.getOrganizationId().isEmpty()) {
                    Organization organization = organizationMapper.selectByPrimaryKey(user.getOrganizationId());
                    userRoleDto.setOrgId(user.getOrganizationId());
                    userRoleDto.setOrgName(organization == null ? "" : organization.getName());
                }
            } else {
                continue;
                // userRoleDto.setUserName("");
            }
            allExtraUsers.add(userRoleDto);
        }
        return allExtraUsers;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * pwc.taxtech.atms.service.UserRoleService#addUsersToRole(java.lang.String,
     * java.lang.String, java.util.List)
     */
    public void addUsersToRole(String roleId, String serviceTypeId, List<String> userIdList) {

        Role role = roleMapper.selectByPrimaryKey(roleId);
        if (role == null) {
            return;
        }

        for (String userId : userIdList) {

            User user = userMapper.selectByPrimaryKey(userId);
            if (user == null) {
                continue;
            }
            // userRole
            UserRole userRole = new UserRole();
            userRole.setId(CommonUtils.getUUID());
            userRole.setUserId(userId);
            userRole.setRoleId(roleId);
            userRole.setServiceTypeId(serviceTypeId);
            userRoleMapper.insert(userRole);

            // operation log
            UpdateLogParams updateLogParams = new UpdateLogParams();
            updateLogParams.setOperationModule(OperationModule.Role.value());
            updateLogParams.setOperationUser(authUserHelper.getCurrentAuditor().get());
            updateLogParams.setOperationContent(user.getUserName());
            updateLogParams.setOperationObject(role.getName());
            updateLogParams.setOperationAction(OperationAction.New.value());
            updateLogParams.setOperateLogType(OperateLogType.OperationLogRole.value());
            updateLogParams.setComment("UserRole");
            operationLogService.addOrDeleteDataAddLog(updateLogParams);
        }

    }

    /*
     * (non-Javadoc)
     *
     * @see pwc.taxtech.atms.service.RoleService#removeUserRole(java.lang.String,
     * java.util.List, java.lang.String)
     */
    public void removeUserRole(String userId, List<String> roleIdList, String serviceTypeId) {

        UserRoleExample example = new UserRoleExample();
        example.createCriteria().andUserIdEqualTo(userId).andRoleIdIn(roleIdList)
                .andServiceTypeIdEqualTo(serviceTypeId);
        userRoleMapper.deleteByExample(example);

        // operation Log
        List<UpdateLogParams> updateLogParamsList = new ArrayList<>();
        for (String roleId : roleIdList) {
            UpdateLogParams updateLogParams = new UpdateLogParams();
            User user = userMapper.selectByPrimaryKey(userId);
            Role role = roleMapper.selectByPrimaryKey(roleId);
            updateLogParams.setOperationModule(OperationModule.Role.value());
            updateLogParams.setOperationUser(authUserHelper.getCurrentAuditor().get());
            updateLogParams.setOperationContent(user == null ? "" : user.getUserName());
            updateLogParams.setOperationObject(role == null ? "" : role.getName());
            updateLogParams.setOperationAction(OperationAction.DeleteUser.value());
            updateLogParams.setOperateLogType(OperateLogType.OperationLogRole.value());
            updateLogParams.setComment("UserRole");
            updateLogParamsList.add(updateLogParams);
        }
        operationLogService.addOrDeleteDataAddLog(updateLogParamsList);

    }

    /*
     * (non-Javadoc)
     *
     * @see pwc.taxtech.atms.service.RoleService#getRoleListByRoleType(int)
     */
    public List<RoleDto> getRoleListByRoleType(String roleTypeId) {

        RoleExample example = new RoleExample();
        example.createCriteria().andServiceTypeIdEqualTo(roleTypeId);
        List<Role> roleList = roleMapper.selectByExample(example);
        List<RoleDto> roleDtoList = new ArrayList<>();
        roleList.stream().forEach(role -> {
            RoleDto roleDto = new RoleDto();
            CommonUtils.copyProperties(role, roleDto);
            roleDtoList.add(roleDto);
        });

        return roleDtoList;

    }

    /*
     * (non-Javadoc)
     *
     * @see pwc.taxtech.atms.service.RoleService#addRoleCategory(java.lang.String,
     * java.lang.String)
     */
    public void addRoleCategory(String roleCategoryName, String roleCategoryId) {

        // check name duplication
        RoleCategoryExample example = new RoleCategoryExample();
        example.createCriteria().andNameEqualTo(roleCategoryName).andIdNotEqualTo(roleCategoryId);
        if (roleCategoryMapper.countByExample(example) > 0) {
            return;
        }
        // role category
        RoleCategory roleCategory = new RoleCategory();
        roleCategory.setId(roleCategoryId);
        roleCategory.setName(roleCategoryName);
        roleCategory.setIsActive(CommonConstants.ADMIN_STATUS);
        roleCategory.setCreateTime(new Date());
        roleCategory.setUpdateTime(new Date());
        roleCategoryMapper.insert(roleCategory);

        // operation log
        UpdateLogParams updateLogParams = new UpdateLogParams();
        updateLogParams.setOperationModule(OperationModule.Role.value());
        updateLogParams.setOperationUser(authUserHelper.getCurrentAuditor().get());
        updateLogParams.setOperationContent("");
        updateLogParams.setOperationObject(roleCategoryName);
        updateLogParams.setOperationAction(OperationAction.New.value());
        updateLogParams.setOperateLogType(OperateLogType.OperationLogRole.value());
        updateLogParams.setComment("RoleCategory");
        operationLogService.addOrDeleteDataAddLog(updateLogParams);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * pwc.taxtech.atms.service.RoleService#updateRoleCategory(java.lang.String,
     * java.lang.String)
     */
    public void updateRoleCategory(String roleCategoryName, String roleCategoryId) {

        RoleCategory roleCategoryToUpdate = roleCategoryMapper.selectByPrimaryKey(roleCategoryId);

        if (roleCategoryToUpdate == null) {
            return;
        }
        RoleCategory roleCategoryOriginal = new RoleCategory();
        CommonUtils.copyProperties(roleCategoryToUpdate, roleCategoryOriginal);

        // role category
        roleCategoryToUpdate.setName(roleCategoryName);
        roleCategoryToUpdate.setUpdateTime(new Date());
        roleCategoryMapper.updateByPrimaryKey(roleCategoryToUpdate);

        // operation log
        UpdateLogParams updateLogParams = new UpdateLogParams();
        updateLogParams.setOperationObject(roleCategoryOriginal.getName());
        updateLogParams.setOriginalState(roleCategoryOriginal);
        updateLogParams.setUpdateState(roleCategoryToUpdate);
        updateLogParams.setOperationUser(authUserHelper.getCurrentAuditor().get());
        updateLogParams.setOperationModule(OperationModule.Role.value());
        updateLogParams.setComment("");
        updateLogParams.setOperationAction(OperationAction.Update.value());
        updateLogParams.setOperateLogType(OperateLogType.OperationLogRole.value());
        operationLogService.updateDataAddLog(updateLogParams);
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * pwc.taxtech.atms.service.RoleService#deleteRoleCategory(java.lang.String)
     */
    public OperationResultDto<?> deleteRoleCategory(String roleCategoryId) {

        RoleCategory roleCategoryToDelete = roleCategoryMapper.selectByPrimaryKey(roleCategoryId);

        if (roleCategoryToDelete == null) {
            return new OperationResultDto<>(false, "RoleCategoryNotFound");
        }

        RoleExample roleExample = new RoleExample();
        roleExample.createCriteria().andRoleCategoryIdEqualTo(roleCategoryId);
        if (roleMapper.countByExample(roleExample) > 0) {
            return new OperationResultDto<>(false, "hasSubRolesWarn");
        }

        // role category
        roleCategoryMapper.deleteByPrimaryKey(roleCategoryId);

        // operation log
        UpdateLogParams updateLogParams = new UpdateLogParams();
        updateLogParams.setOperationModule(OperationModule.Role.value());
        updateLogParams.setOperationUser(authUserHelper.getCurrentAuditor().get());
        updateLogParams.setOperationContent("");
        updateLogParams.setOperationObject(roleCategoryToDelete.getName());
        updateLogParams.setOperationAction(OperationAction.Delete.value());
        updateLogParams.setOperateLogType(OperateLogType.OperationLogRole.value());
        updateLogParams.setComment("RoleCategory");
        operationLogService.addOrDeleteDataAddLog(updateLogParams);

        return OperationResultDto.success();
    }

    /*
     * (non-Javadoc)
     *
     * @see pwc.taxtech.atms.service.RoleService#addRole(pwc.taxtech.atms.dto.role.
     * RoleDisplayDto)
     */
    public String addRole(RoleDisplayDto roleDisplayDto) {

        // check role exist by roleId
        RoleExample roleExample = new RoleExample();
        roleExample.createCriteria().andNameEqualTo(roleDisplayDto.getName().trim())
                .andServiceTypeIdEqualTo(roleDisplayDto.getServiceTypeId());
        if (roleMapper.countByExample(roleExample) > 0) {
            return "-1";
        }

        // add role
        Role roleToAdd = new Role();
        CommonUtils.copyProperties(roleDisplayDto, roleToAdd);
        roleToAdd.setId(CommonUtils.getUUID());
        roleToAdd.setName(roleDisplayDto.getName().trim());
        roleToAdd.setCreateTime(new Date());
        roleToAdd.setUpdateTime(new Date());
        roleMapper.insert(roleToAdd);

        // operation log for add role
        UpdateLogParams updateLogParams = new UpdateLogParams();
        updateLogParams.setOperationModule(OperationModule.Role.value());
        updateLogParams.setOperationUser(authUserHelper.getCurrentAuditor().get());
        updateLogParams.setOperationContent("");
        updateLogParams.setOperationObject(roleToAdd.getName());
        updateLogParams.setOperationAction(OperationAction.New.value());
        updateLogParams.setOperateLogType(OperateLogType.OperationLogRole.value());
        updateLogParams.setComment("Role");
        operationLogService.addOrDeleteDataAddLog(updateLogParams);

        // 增加权限
        if (!Collections.isEmpty(roleDisplayDto.getPermissionIds())) {
            for (String permissionId : roleDisplayDto.getPermissionIds()) {

                Permission permission = permissionMapper.selectByPrimaryKey(permissionId);
                if (permission == null) {
                    continue;
                }
                RolePermission rolePermission = new RolePermission();
                rolePermission.setId(CommonUtils.getUUID());
                rolePermission.setPermissionId(permissionId);
                rolePermission.setRoleId(roleToAdd.getId());
                rolePermissionMapper.insert(rolePermission);

                // 增加权限日志
                UpdateLogParams permissionLogParams = new UpdateLogParams();
                permissionLogParams.setOperationModule(OperationModule.Role.value());
                permissionLogParams.setOperationUser(authUserHelper.getCurrentAuditor().get());
                permissionLogParams.setOperationContent(permission.getName());
                permissionLogParams.setOperationObject(roleToAdd.getName());
                permissionLogParams.setOperationAction(OperationAction.AddNewPermission.value());
                permissionLogParams.setOperateLogType(OperateLogType.OperationLogRole.value());
                permissionLogParams.setComment("Permission");
                operationLogService.addOrDeleteDataAddLog(permissionLogParams);
            }
        }

        return roleToAdd.getId();
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * pwc.taxtech.atms.service.RoleService#updateRole(pwc.taxtech.atms.dto.role.
     * UpdateRoleInfo, java.lang.String)
     */
    public void updateRole(UpdateRoleInfo updateRole, String roleId) {

        if (updateRole == null || updateRole.getUpdateRolePermissionDtoList() == null
                || updateRole.getRoleName() == null) {
            return;
        }

        // update role info
        Role roleToUpdate = roleMapper.selectByPrimaryKey(roleId);
        if (roleToUpdate == null) {
            return;
        }
        Role roleOriginal = new Role();
        CommonUtils.copyProperties(roleToUpdate, roleOriginal);
        roleToUpdate.setName(updateRole.getRoleName().trim());
        roleToUpdate.setDescription(updateRole.getRoleDescription());
        roleMapper.updateByPrimaryKey(roleToUpdate);

        // operation log for role update
        UpdateLogParams updateRoleLogParams = new UpdateLogParams();
        updateRoleLogParams.setOperationObject(roleOriginal.getName());
        updateRoleLogParams.setOriginalState(roleOriginal);
        updateRoleLogParams.setUpdateState(roleToUpdate);
        updateRoleLogParams.setOperationUser(authUserHelper.getCurrentAuditor().get());
        updateRoleLogParams.setOperationModule(OperationModule.Role.value());
        updateRoleLogParams.setComment("");
        updateRoleLogParams.setOperationAction(OperationAction.Update.value());
        updateRoleLogParams.setOperateLogType(OperateLogType.OperationLogRole.value());
        operationLogService.updateDataAddLog(updateRoleLogParams);

        // 判断新增的权限和删除的权限
        RolePermissionExample rolePermissionExample = new RolePermissionExample();
        rolePermissionExample.createCriteria().andRoleIdEqualTo(roleId);
        List<RolePermission> originalRolePermissionList = rolePermissionMapper.selectByExample(rolePermissionExample);
        Set<String> originalPermissionIdList = originalRolePermissionList.stream().map(sa -> sa.getPermissionId())
                .collect(Collectors.toSet());
        Set<String> updatePermissionIdList = updateRole.getUpdateRolePermissionDtoList().stream().map(sa -> sa.getId())
                .collect(Collectors.toSet());
        Set<String> unionPermissionIdList = new HashSet<>();
        unionPermissionIdList.addAll(originalPermissionIdList);
        unionPermissionIdList.addAll(updatePermissionIdList);

        Set<String> removePermissionIdList = unionPermissionIdList.stream()
                .filter(sa -> originalPermissionIdList.contains(sa) && !updatePermissionIdList.contains(sa))
                .collect(Collectors.toSet());
        Set<String> addPermissionIdList = unionPermissionIdList.stream()
                .filter(sa -> !originalPermissionIdList.contains(sa) && updatePermissionIdList.contains(sa))
                .collect(Collectors.toSet());

        // 删除权限
        for (String permissionId : removePermissionIdList) {
            Permission permission = permissionMapper.selectByPrimaryKey(permissionId);
            if (permission == null) {
                continue;
            }
            RolePermissionExample example = new RolePermissionExample();
            example.createCriteria().andRoleIdEqualTo(roleId).andPermissionIdEqualTo(permissionId);
            rolePermissionMapper.deleteByExample(example);

            UpdateLogParams permissionLogParams = new UpdateLogParams();
            permissionLogParams.setOperationModule(OperationModule.Role.value());
            permissionLogParams.setOperationUser(authUserHelper.getCurrentAuditor().get());
            permissionLogParams.setOperationContent(permission.getName());
            permissionLogParams.setOperationObject(roleOriginal.getName());
            permissionLogParams.setOperationAction(OperationAction.Delete.value());
            permissionLogParams.setOperateLogType(OperateLogType.OperationLogRole.value());
            permissionLogParams.setComment("Permission");
            operationLogService.addOrDeleteDataAddLog(permissionLogParams);
        }

        // 新增的权限
        for (String permissionId : addPermissionIdList) {
            Permission permission = permissionMapper.selectByPrimaryKey(permissionId);
            if (permission == null) {
                continue;
            }
            RolePermission rolePermission = new RolePermission();
            rolePermission.setId(CommonUtils.getUUID());
            rolePermission.setPermissionId(permissionId);
            rolePermission.setRoleId(roleId);
            rolePermissionMapper.insert(rolePermission);

            UpdateLogParams permissionLogParams = new UpdateLogParams();
            permissionLogParams.setOperationModule(OperationModule.Role.value());
            permissionLogParams.setOperationUser(authUserHelper.getCurrentAuditor().get());
            permissionLogParams.setOperationContent(permission.getName());
            permissionLogParams.setOperationObject(roleOriginal.getName());
            permissionLogParams.setOperationAction(OperationAction.New.value());
            permissionLogParams.setOperateLogType(OperateLogType.OperationLogRole.value());
            permissionLogParams.setComment("Permission");
            operationLogService.addOrDeleteDataAddLog(permissionLogParams);
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * pwc.taxtech.atms.service.RoleService#validateRoleNameUnique(java.lang.String,
     * java.lang.String)
     */
    public boolean validateRoleNameUnique(String roleName, String oldRoleName) {

        if (roleName.trim().equals(oldRoleName.trim())) {
            return true;
        }

        RoleExample example = new RoleExample();
        example.createCriteria().andNameEqualTo(roleName.trim());
        if (roleMapper.countByExample(example) > 0) {
            return false;
        }
        return true;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * pwc.taxtech.atms.service.RoleService#deleteRole(pwc.taxtech.atms.dto.role.
     * RoleDto)
     */
    public void deleteRole(RoleDto roleDto) {

        if (roleDto == null || roleDto.getId() == null || roleDto.getId().isEmpty()) {
            return;
        }
        // delete rolePermission
        RolePermissionExample rolePermissionExample = new RolePermissionExample();
        rolePermissionExample.createCriteria().andRoleIdEqualTo(roleDto.getId());
        rolePermissionMapper.deleteByExample(rolePermissionExample);

        // delete role
        roleMapper.deleteByPrimaryKey(roleDto.getId());

        // operation log
        UpdateLogParams permissionLogParams = new UpdateLogParams();
        permissionLogParams.setOperationModule(OperationModule.Role.value());
        permissionLogParams.setOperationUser(authUserHelper.getCurrentAuditor().get());
        permissionLogParams.setOperationContent(roleDto.getName());
        permissionLogParams.setOperationObject(roleDto.getName());
        permissionLogParams.setOperationAction(OperationAction.Delete.value());
        permissionLogParams.setOperateLogType(OperateLogType.OperationLogRole.value());
        permissionLogParams.setComment("Role");
        operationLogService.addOrDeleteDataAddLog(permissionLogParams);

    }

    /*
     * (non-Javadoc)
     *
     * @see pwc.taxtech.atms.service.RoleService#checkUserRole(java.lang.String)
     */
    public boolean checkUserRole(String roleId) {

        if (roleId != null) {
            UserRoleExample userRoleExample = new UserRoleExample();
            userRoleExample.createCriteria().andRoleIdEqualTo(roleId);
            Long userRoleCount = userRoleMapper.countByExample(userRoleExample);

            UserDimensionValueRoleExample userDimensionValueRoleExample = new UserDimensionValueRoleExample();
            userDimensionValueRoleExample.createCriteria().andRoleIdEqualTo(roleId);
            Long userDimensionValueRoleCount = userDimensionValueRoleMapper
                    .countByExample(userDimensionValueRoleExample);

            UserOrganizationRoleExample userOrganizationRoleExample = new UserOrganizationRoleExample();
            userOrganizationRoleExample.createCriteria().andRoleIdEqualTo(roleId);
            Long userOrganizationRoleCount = userOrganizationRoleMapper.countByExample(userOrganizationRoleExample);

            if (userRoleCount > 0 || userDimensionValueRoleCount > 0 || userOrganizationRoleCount > 0) {
                return false;
            }
        }
        return true;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * pwc.taxtech.atms.service.RoleService#getUserRoleList(pwc.taxtech.atms.dto.
     * user.UserRoleDimensionValueDto)
     */
    public List<UserRoleInfo> getUserRoleList(UserRoleDimensionValueDto userRoleDimensionValueDto) {

        if (userRoleDimensionValueDto.getOrganizationId() == null
                || userRoleDimensionValueDto.getOrganizationId().isEmpty()) {
            return new ArrayList<>();
        }

        // 用户列表
        List<User> users = userMapper.selectByExample(null);
        List<VMUser> userList = new ArrayList<>();
        users.stream().forEach(user -> {
            VMUser vmUser = new VMUser();
            CommonUtils.copyProperties(user, vmUser);
            userList.add(vmUser);
        });

        // 角色列表
        List<Role> roles = roleMapper.selectByExample(null);
        List<NameDto> roleList = new ArrayList<>();
        roles.stream().forEach(role -> {
            NameDto nameDto = new NameDto();
            CommonUtils.copyProperties(role, nameDto);
            roleList.add(nameDto);
        });

        // 获取原始角色列表
        List<UserRoleSimpleDto> userRoleList = getOriginalUserRoleList(roleList);

        // 用户维度 排除 不继承的 维度
        UserDimensionValueOrgExample userDimensionValueOrgExample = new UserDimensionValueOrgExample();
        userDimensionValueOrgExample.createCriteria()
                .andOrganizationIdEqualTo(userRoleDimensionValueDto.getOrganizationId())
                .andIsHeritableEqualTo(CommonConstants.IsHeritable);
        List<UserDimensionValueOrg> excludeHeritableList = userDimensionValueOrgMapper
                .selectByExample(userDimensionValueOrgExample);
        UserDimensionValueExample userDimensionValueExample = new UserDimensionValueExample();
        if (!excludeHeritableList.isEmpty()) {
            List<String> excludeUserDimensionValueIdList = excludeHeritableList.stream()
                    .map(sa -> sa.getUserDimensionValueId()).collect(Collectors.toList());
            userDimensionValueExample.createCriteria().andIdNotIn(excludeUserDimensionValueIdList);
        }
        List<UserDimensionValue> userDimensionValueList = userDimensionValueMapper
                .selectByExample(userDimensionValueExample);

        // 维度角色列表
        List<UserDimensionValueRoleDto> dimensionValueRoleList = getDimensionValueRoleList(roleList);

        // 机构角色列表
        List<UserOrganizationRoleDto> userOrganizationRoleList = getUserOrganizationRoleList(roleList);

        // 用户机构
        UserOrganizationExample userOrganizationExample = new UserOrganizationExample();
        userOrganizationExample.createCriteria()
                .andOrganizationIdEqualTo(userRoleDimensionValueDto.getOrganizationId());
        List<UserOrganization> thisUserOrganizationList = userOrganizationMapper
                .selectByExample(userOrganizationExample);

        // 机构列表
        Organization organization = organizationMapper
                .selectByPrimaryKey(userRoleDimensionValueDto.getOrganizationId());
        // 禁用的机构,就不拿用户设置信息了
        if (organization == null) {
            return new ArrayList<UserRoleInfo>();
        }

        // 机构维度设置列表
        List<DimensionValueOrgDto> dimensionValueOrgList = getDimensionValueOrgDtoList();

        List<DimensionValueOrgDto> thisDimensionValueOrgList = dimensionValueOrgList.stream()
                .filter(sa -> sa.getOrganizationId().equals(userRoleDimensionValueDto.getOrganizationId()))
                .collect(Collectors.toList());

        return getAllUserRoleInfoListByOrg(thisUserOrganizationList, organization, userList, userRoleList,
                userDimensionValueList, thisDimensionValueOrgList, userOrganizationRoleList, dimensionValueRoleList);
    }

    /**
     * 获取用户 的可访问权限 不可访问的也要显示
     *
     * @return List<UserRoleInfo>
     */
    private List<UserRoleInfo> getAllUserRoleInfoListByOrg(List<UserOrganization> thisUserOrganizationList,
                                                           Organization organization, List<VMUser> userList, List<UserRoleSimpleDto> userRoleList,
                                                           List<UserDimensionValue> pUserDimensionValueList, List<DimensionValueOrgDto> dimensionValueOrgList,
                                                           List<UserOrganizationRoleDto> userOrganizationRoleList,
                                                           List<UserDimensionValueRoleDto> dimensionValueRoleList) {

        List<UserRoleInfo> retList = new ArrayList<>();

        // 机构在维度上的设置
        List<UserDimensionValue> userDimensionValueList = new ArrayList<>();
        for (UserDimensionValue userDimensionValue : pUserDimensionValueList) {
            for (DimensionValueOrgDto dimensionValueOrg : dimensionValueOrgList) {
                if (userDimensionValue.getDimensionValueId().equals(dimensionValueOrg.getDimensionValueId())) {
                    userDimensionValueList.add(userDimensionValue);
                    break;
                }
            }
        }

        // 1 机构上设置了,维度上也设置了
        for (UserOrganization userOrganization : thisUserOrganizationList) {

            Optional<VMUser> optional = userList.stream()
                    .filter(user -> user.getId().equals(userOrganization.getUserId())).findFirst();
            if (!optional.isPresent()) {
                continue;
            }
            VMUser user = optional.get();

            // 不可继承的只需要附加角色
            UserRoleInfo userRoleInfo = new UserRoleInfo();
            userRoleInfo.setId(userOrganization.getUserId());
            userRoleInfo.setOrganizationId(organization.getId());
            userRoleInfo.setOrganizationName(organization.getName());
            userRoleInfo.setRoleInfoList(new ArrayList<>());
            userRoleInfo.setIsAccessible(userOrganization.getIsAccessible());
            userRoleInfo.setStatus(user.getStatus());
            userRoleInfo.setEmail(user.getEmail());
            userRoleInfo.setUserName(user.getUserName());
            userRoleInfo.setAreaId(organization.getAreaId());
            userRoleInfo.setBusinessUnitId(organization.getBusinessUnitId());
            userRoleInfo.setServiceTypeId("");

            if (userRoleInfo.isAccessible) {

                // 机构在维度上的设置
                List<UserDimensionValue> thisUserDimensionValueList = userDimensionValueList.stream()
                        .filter(sa -> sa.getUserId().equals(userOrganization.getUserId())).collect(Collectors.toList());

                // 任意一个维度不可访问都不可访问
                Optional<UserDimensionValue> anyInAccessible = thisUserDimensionValueList.stream()
                        .filter(sa -> !sa.getIsAccessible()).findAny();
                if (anyInAccessible.isPresent()) {
                    userRoleInfo.setIsAccessible(CommonConstants.IsNotAccessible);
                    retList.add(userRoleInfo);
                    continue;
                }

                // 原始角色
                Optional<UserDimensionValue> anyHasOriginalRole = thisUserDimensionValueList.stream()
                        .filter(sa -> sa.getHasOriginalRole()).findAny();
                if (userOrganization.getHasOriginalRole() || anyHasOriginalRole.isPresent()) {

                    List<UserRoleSimpleDto> thisUserRoleList = userRoleList.stream()
                            .filter(userRole -> userRole.getUserId().equals(userOrganization.getUserId()))
                            .collect(Collectors.toList());
                    thisUserRoleList.forEach(userRole -> userRole.setId(null));
                    List<RoleInfo> origianlRoleList = new ArrayList<>();
                    thisUserRoleList.stream().distinct().forEach(userRole -> {
                        RoleInfo roleInfo = new RoleInfo();
                        roleInfo.setId(userRole.getRoleId());
                        roleInfo.setName(userRole.getRoleName());
                        origianlRoleList.add(roleInfo);
                    });
                    if (!origianlRoleList.isEmpty()) {
                        userRoleInfo.setRoleInfoList(origianlRoleList);
                    }
                }

                // 维度角色
                List<RoleInfo> dimensionRoleListNoDistinct = new ArrayList<>();
                for (UserDimensionValueRoleDto userDimensionValueRole : dimensionValueRoleList) {
                    for (UserDimensionValue userDimensionValue : thisUserDimensionValueList) {
                        if (userDimensionValueRole.getUserDimensionValueId().equals(userDimensionValue.getId())) {
                            Optional<RoleInfo> alreadyInRoleInfoList = userRoleInfo.getRoleInfoList().stream()
                                    .filter(userRole -> userRole.getId().equals(userDimensionValueRole.getRoleId()))
                                    .findAny();
                            if (!alreadyInRoleInfoList.isPresent()) {
                                RoleInfo roleInfo = new RoleInfo();
                                roleInfo.setId(userDimensionValueRole.getRoleId());
                                roleInfo.setName(userDimensionValueRole.getRoleName());
                                dimensionRoleListNoDistinct.add(roleInfo);
                                break;
                            }
                        }
                    }
                }
                List<RoleInfo> dimensionRoleList = dimensionRoleListNoDistinct.stream().distinct()
                        .collect(Collectors.toList());
                userRoleInfo.getRoleInfoList().addAll(dimensionRoleList);

                // 机构角色
                List<RoleInfo> userOrgRoleListNoDistinct = new ArrayList<>();
                for (UserOrganizationRoleDto userOrganizationRoleDto : userOrganizationRoleList) {
                    if (userOrganizationRoleDto.getUserOrganizationId().equals(userOrganization.getId())) {
                        Optional<RoleInfo> alreadyInRoleInfoList = userRoleInfo.getRoleInfoList().stream()
                                .filter(userRole -> userRole.getId().equals(userOrganizationRoleDto.getRoleId()))
                                .findAny();
                        if (!alreadyInRoleInfoList.isPresent()) {
                            RoleInfo roleInfo = new RoleInfo();
                            roleInfo.setId(userOrganizationRoleDto.getRoleId());
                            roleInfo.setName(userOrganizationRoleDto.getRoleName());
                            userOrgRoleListNoDistinct.add(roleInfo);
                            break;
                        }
                    }
                }
                List<RoleInfo> userOrgRoleList = userOrgRoleListNoDistinct.stream().distinct()
                        .collect(Collectors.toList());
                userRoleInfo.getRoleInfoList().addAll(userOrgRoleList);
            }
            retList.add(userRoleInfo);
        }

        // 2 机构上没有设置 维度上设置了
        List<UserDimensionValue> dimensionOnlyList = new ArrayList<>();
        for (UserDimensionValue userDimensionValue : userDimensionValueList) {
            Optional<UserRoleInfo> alreadyInRetList = retList.stream()
                    .filter(sa -> sa.getId().equals(userDimensionValue.getUserId())).findAny();
            if (!alreadyInRetList.isPresent()) {
                dimensionOnlyList.add(userDimensionValue);
            }
        }
        Set<String> userIdSet = dimensionOnlyList.stream().map(sa -> sa.getUserId()).collect(Collectors.toSet());

        for (String userId : userIdSet) {
            Optional<VMUser> userExist = userList.stream().filter(user -> user.getId().equals(userId)).findFirst();
            if (!userExist.isPresent()) {
                continue;
            }
            VMUser user = userExist.get();

            UserRoleInfo userRoleInfo = new UserRoleInfo();
            userRoleInfo.setId(user.getId());
            userRoleInfo.setOrganizationId(organization.getId());
            userRoleInfo.setOrganizationName(organization.getName());
            userRoleInfo.setRoleInfoList(new ArrayList<>());
            userRoleInfo.setIsAccessible(CommonConstants.IsAccessible);
            userRoleInfo.setStatus(user.getStatus());
            userRoleInfo.setEmail(user.getEmail());
            userRoleInfo.setUserName(user.getUserName());
            userRoleInfo.setAreaId(organization.getAreaId());
            userRoleInfo.setBusinessUnitId(organization.getBusinessUnitId());
            userRoleInfo.setServiceTypeId("");

            List<UserDimensionValue> userDimensionTempList = dimensionOnlyList.stream()
                    .filter(sa -> sa.getUserId().equals(userId)).collect(Collectors.toList());
            Optional<UserDimensionValue> anyInAccessible = userDimensionTempList.stream()
                    .filter(sa -> !sa.getIsAccessible()).findAny();
            if (userDimensionTempList.isEmpty() || anyInAccessible.isPresent()) {
                userRoleInfo.setIsAccessible(CommonConstants.IsNotAccessible);
                retList.add(userRoleInfo);
                continue;
            }

            // 机构在维度上的设置
            List<UserDimensionValue> thisUserDimensionValueList = new ArrayList<>();
            for (UserDimensionValue userDimensionValue : userDimensionTempList) {
                for (DimensionValueOrgDto dimensionValueOrgDto : dimensionValueOrgList) {
                    if (userDimensionValue.getDimensionValueId().equals(dimensionValueOrgDto.getDimensionValueId())
                            && userDimensionValue.getUserId().equals(userId)) {
                        thisUserDimensionValueList.add(userDimensionValue);
                        break;
                    }
                }
            }

            // 任意一个维度不可访问都不可访问
            anyInAccessible = thisUserDimensionValueList.stream().filter(sa -> !sa.getIsAccessible()).findAny();
            if (anyInAccessible.isPresent()) {
                userRoleInfo.setIsAccessible(CommonConstants.IsNotAccessible);
                retList.add(userRoleInfo);
                continue;
            }

            // 原始角色
            Optional<UserDimensionValue> anyHasOriginalRole = thisUserDimensionValueList.stream()
                    .filter(sa -> sa.getHasOriginalRole()).findAny();
            if (anyHasOriginalRole.isPresent()) {

                List<UserRoleSimpleDto> thisUserRoleList = userRoleList.stream()
                        .filter(userRole -> userRole.getUserId().equals(userId)).collect(Collectors.toList());
                thisUserRoleList.forEach(userRole -> userRole.setId(null));
                List<RoleInfo> origianlRoleList = new ArrayList<>();
                thisUserRoleList.stream().distinct().forEach(userRole -> {
                    RoleInfo roleInfo = new RoleInfo();
                    roleInfo.setId(userRole.getRoleId());
                    roleInfo.setName(userRole.getRoleName());
                    origianlRoleList.add(roleInfo);
                });
                if (!origianlRoleList.isEmpty()) {
                    userRoleInfo.setRoleInfoList(origianlRoleList);
                }
            }

            // 维度角色
            List<RoleInfo> dimensionRoleListNoDistinct = new ArrayList<>();
            for (UserDimensionValueRoleDto userDimensionValueRole : dimensionValueRoleList) {
                for (UserDimensionValue userDimensionValue : thisUserDimensionValueList) {
                    if (userDimensionValueRole.getUserDimensionValueId().equals(userDimensionValue.getId())) {
                        Optional<RoleInfo> alreadyInRoleInfoList = userRoleInfo.getRoleInfoList().stream()
                                .filter(userRole -> userRole.getId().equals(userDimensionValueRole.getRoleId()))
                                .findAny();
                        if (!alreadyInRoleInfoList.isPresent()) {
                            RoleInfo roleInfo = new RoleInfo();
                            roleInfo.setId(userDimensionValueRole.getRoleId());
                            roleInfo.setName(userDimensionValueRole.getRoleName());
                            dimensionRoleListNoDistinct.add(roleInfo);
                            break;
                        }
                    }
                }
            }
            List<RoleInfo> dimensionRoleList = dimensionRoleListNoDistinct.stream().distinct()
                    .collect(Collectors.toList());
            userRoleInfo.getRoleInfoList().addAll(dimensionRoleList);

            retList.add(userRoleInfo);
        }

        return retList;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * pwc.taxtech.atms.service.RoleService#getAllRolePermission(java.lang.String)
     */
    public List<RolePermissionDto> getAllRolePermission(String serviceTypeId) {

        List<RolePermissionDto> rolePermissionDtoList = new ArrayList<>();

        RoleExample roleExample = new RoleExample();
        roleExample.createCriteria().andServiceTypeIdEqualTo(serviceTypeId);
        List<Role> roleList = roleMapper.selectByExample(roleExample);
        for (Role role : roleList) {
            RolePermissionDto rolePermissionDto = new RolePermissionDto();
            rolePermissionDto.setRoleId(role.getId());
            rolePermissionDto.setRoleName(role.getName());

            List<RolePermission> rolePermissionList = rolePermissionMapper
                    .selectByRoleAndServiceTypeWithAssociation(role.getId(), serviceTypeId);
            List<PermissionDto> permissionDtoNoDistinct = new ArrayList<>();
            for (RolePermission rolePermission : rolePermissionList) {
                if (rolePermission.getPermission().getIsActive()) {
                    PermissionDto permissionDto = new PermissionDto();
                    permissionDto.setId(rolePermission.getPermission().getId());
                    permissionDto.setName(rolePermission.getPermission().getName());
                    permissionDto.setParentId(rolePermission.getPermission().getParentId());
                    permissionDtoNoDistinct.add(permissionDto);
                }
            }
            List<PermissionDto> permissionDtoList = permissionDtoNoDistinct.stream().distinct()
                    .collect(Collectors.toList());
            rolePermissionDto.setPermissionList(permissionDtoList);

            rolePermissionDtoList.add(rolePermissionDto);
        }
        return rolePermissionDtoList;
    }

    /*
     * (non-Javadoc)
     *
     * @see
     * pwc.taxtech.atms.service.RoleService#updateUserRole(pwc.taxtech.atms.dto.user
     * .UserRoleUpdateDto)
     */
    public void updateUserRole(UserRoleUpdateDto userRoleUpdateDto) {

        // remove user role
        if (userRoleUpdateDto.getRemovedRoles() != null && !userRoleUpdateDto.getRemovedRoles().isEmpty()) {
            UserRoleExample userRoleExample = new UserRoleExample();
            userRoleExample.createCriteria().andUserIdEqualTo(userRoleUpdateDto.getUserId())
                    .andRoleIdIn(userRoleUpdateDto.getRemovedRoles());
            userRoleMapper.deleteByExample(userRoleExample);
        }

        // add user role
        if (userRoleUpdateDto.getAddedRoles() != null && !userRoleUpdateDto.getAddedRoles().isEmpty()) {
            for (String roleId : userRoleUpdateDto.getAddedRoles()) {
                UserRole userRole = new UserRole();
                userRole.setId(CommonUtils.getUUID());
                userRole.setUserId(userRoleUpdateDto.getUserId());
                userRole.setRoleId(roleId);
                userRole.setServiceTypeId(ServiceTypeEnum.VAT.value().toString());
                userRoleMapper.insert(userRole);
            }
        }

    }

    /*
     * (non-Javadoc)
     *
     * @see
     * pwc.taxtech.atms.service.RoleService#updateDimensionValues(pwc.taxtech.atms.
     * dto.dimension.DimensionValueUpdateDto)
     */
    public void updateDimensionValues(DimensionValueUpdateDto dimensionValueUpdateDto) {

        if (dimensionValueUpdateDto.getAddedDimensions() != null
                && !dimensionValueUpdateDto.getAddedDimensions().isEmpty()) {
            for (SimpleDimensionDto dimension : dimensionValueUpdateDto.getAddedDimensions()) {
                UserDimensionValue userDimensionValue = new UserDimensionValue();
                userDimensionValue.setId(CommonUtils.getUUID());
                userDimensionValue.setUserId(dimensionValueUpdateDto.getUserId());
                userDimensionValue.setDimensionId(dimension.getParentId());
                userDimensionValue.setDimensionValueId(dimension.getId());
                userDimensionValue.setIsAccessible(CommonConstants.IsAccessible);
                userDimensionValue.setHasOriginalRole(CommonConstants.HasOriginalRole);

                userDimensionValueMapper.insert(userDimensionValue);
            }
        }

    }

    /*
     * (non-Javadoc)
     *
     * @see pwc.taxtech.atms.service.RoleService#updateUserOrg(java.util.List,
     * java.lang.String)
     */
    public void updateUserOrg(List<String> orgIdList, String userId) {

        if (orgIdList != null && !orgIdList.isEmpty()) {
            for (String orgId : orgIdList) {

                UserOrganization userOrganization = new UserOrganization();
                userOrganization.setId(CommonUtils.getUUID());
                userOrganization.setUserId(userId);
                userOrganization.setOrganizationId(orgId);
                userOrganization.setIsAccessible(CommonConstants.IsAccessible);
                userOrganization.setHasOriginalRole(CommonConstants.HasOriginalRole);

                userOrganizationMapper.insert(userOrganization);
            }
        }

    }

    public List<DimensionRole> getDimensionRoleUserList(String dimensionId, String dimensionValueId) {
        List<DimensionRole> retList = new ArrayList<>();
        if (DimensionConstant.OrgSubChildrenId.equals(dimensionId)) {
            UserRoleDimensionValueDto userRoleDimensionValueDto = new UserRoleDimensionValueDto();
            userRoleDimensionValueDto.setOrganizationId(dimensionValueId);
            List<UserRoleInfo> userRoleInfoList = getUserRoleList(userRoleDimensionValueDto);
            for (UserRoleInfo user : userRoleInfoList) {
                for (RoleInfo role : user.getRoleInfoList()) {
                    DimensionRole roleCount = retList.stream()
                            .filter(sa -> Objects.equals(sa.getRoleId(), role.getId())).findFirst().orElse(null);
                    if (roleCount != null) {
                        if (roleCount.getUserList().stream()
                                .noneMatch(sa -> Objects.equals(sa.getId(), user.getId()))) {
                            roleCount.getUserList().add(generateUserDto(user));
                        }
                    } else {
                        DimensionRole model = new DimensionRole();
                        model.setUserList(new ArrayList<>());
                        model.setRoleId(role.getId());
                        model.setDimensionId(dimensionId);
                        model.setDimensionValueId(dimensionValueId);
                        model.setRoleName(role.getName());

                        model.getUserList().add(generateUserDto(user));
                        retList.add(model);
                    }
                }
            }
            return retList;
        }
        // 用户维度
        List<UserDimensionValue> userDimensionValueList = getUserDimensionValueList(dimensionId, dimensionValueId);
        // 原始角色列表
        List<UserRole> userRoleList = userRoleMapper.selectByExample(new UserRoleExample());
        // 用户维度角色
        List<UserDimensionValueRole> userDimensionValueRoleList = userDimensionValueRoleMapper
                .selectByExample(new UserDimensionValueRoleExample());
        // 用户维度角色dto
        List<UserDimensionValueRoleDto> userDimensionValueRoleDtoList = new ArrayList<>();
        for (UserDimensionValueRole p : userDimensionValueRoleList) {
            if (p == null || p.getUserDimensionValueId() == null) {
                continue;
            }
            for (UserDimensionValue q : userDimensionValueList) {
                if (p.getUserDimensionValueId().equals(q.getId())) {
                    UserDimensionValueRoleDto userDimensionValueRoleDto = CommonUtils.copyProperties(q,
                            new UserDimensionValueRoleDto());
                    userDimensionValueRoleDto.setId(p.getId());
                    userDimensionValueRoleDto.setRoleId(p.getRoleId());
                    userDimensionValueRoleDto.setRoleName("");
                    userDimensionValueRoleDto.setUserDimensionValueId(p.getUserDimensionValueId());
                    userDimensionValueRoleDtoList.add(userDimensionValueRoleDto);
                }
            }
        }
        // 加上包含原始角色
        for (UserDimensionValue userDimensionValue : userDimensionValueList) {
            if (BooleanUtils.isTrue(userDimensionValue.getHasOriginalRole())) {
                List<UserDimensionValueRoleDto> origianlRoleList = new ArrayList<>();
                for (UserRole p : userRoleList) {
                    if (Objects.equals(p.getUserId(), userDimensionValue.getUserId())
                            && userDimensionValueRoleDtoList.stream()
                            .noneMatch(sa -> Objects.equals(sa.getDimensionValueId(),
                                    userDimensionValue.getDimensionValueId())
                                    && Objects.equals(sa.getUserId(), userDimensionValue.getUserId())
                                    && Objects.equals(sa.getRoleId(), p.getRoleId()))) {
                        UserDimensionValueRoleDto userDimensionValueRoleDto = CommonUtils
                                .copyProperties(userDimensionValue, new UserDimensionValueRoleDto());
                        userDimensionValueRoleDto.setId(p.getId());
                        userDimensionValueRoleDto.setIsAccessible(CommonConstants.ISACCESSIBLE_YES);
                        userDimensionValueRoleDto.setRoleId(p.getRoleId());
                        userDimensionValueRoleDto.setRoleName("");
                        userDimensionValueRoleDto.setUserDimensionValueId(userDimensionValue.getId());
                        origianlRoleList.add(userDimensionValueRoleDto);
                    }
                }
                userDimensionValueRoleDtoList.addAll(origianlRoleList);
            }
        }
        // 用户列表
        List<User> userList = userMapper.selectByExample(new UserExample());
        // 角色列表
        List<Role> roleList = roleMapper.selectByExample(new RoleExample());
        List<UserDimensionValueRoleDto> group = userDimensionValueRoleDtoList.stream()
                .map(this::convertUserDimensionValueRoleDtoForDistinct).distinct().collect(Collectors.toList());
        for (UserDimensionValueRoleDto item : group) {
            Role role = roleList.stream().filter(sa -> Objects.equals(sa.getId(), item.getRoleId())).findFirst()
                    .orElse(null);
            if (role == null) {
                continue;
            }
            List<UserDimensionValueRoleDto> valueList = userDimensionValueRoleDtoList.stream()
                    .filter(sa -> Objects.equals(sa.getDimensionId(), item.getDimensionId())
                            && Objects.equals(sa.getDimensionValueId(), item.getDimensionValueId())
                            && Objects.equals(sa.getRoleId(), item.getRoleId()))
                    .collect(Collectors.toList());
            DimensionRole model = new DimensionRole();
            model.setUserList(new ArrayList<>());
            model.setRoleId(item.getRoleId());
            model.setDimensionId(item.getDimensionId());
            model.setDimensionValueId(item.getDimensionValueId());
            model.setRoleName(role.getName());
            List<UserDto> userDtoList = userList.stream()
                    .filter(p -> valueList.stream().anyMatch(sa -> Objects.equals(sa.getUserId(), p.getId())))
                    .map(u -> CommonUtils.copyProperties(u, new UserDto())).distinct().collect(Collectors.toList());
            model.setUserList(userDtoList);
            retList.add(model);
        }
        return retList;
    }

    private UserDimensionValueRoleDto convertUserDimensionValueRoleDtoForDistinct(UserDimensionValueRoleDto uo) {
        UserDimensionValueRoleDto userDimensionValueRoleDto = new UserDimensionValueRoleDto();
        userDimensionValueRoleDto.setDimensionId(uo.getDimensionId());
        userDimensionValueRoleDto.setDimensionValueId(uo.getDimensionValueId());
        userDimensionValueRoleDto.setRoleId(uo.getRoleId());
        return userDimensionValueRoleDto;
    }

    private UserDto generateUserDto(UserRoleInfo userRoleInfo) {
        UserDto userDto = new UserDto();
        userDto.setId(userRoleInfo.getId());
        userDto.setUserName(userRoleInfo.getUserName());
        userDto.setEmail(userRoleInfo.getEmail());
        return userDto;
    }

    private List<UserDimensionValue> getUserDimensionValueList(String dimensionId, String dimensionValueId) {
        List<UserDimensionValue> userRoleUserRoleDimensionList = null;
        if (!StringUtils.hasText(dimensionId) && !StringUtils.hasText(dimensionValueId)) {
            userRoleUserRoleDimensionList = userDimensionValueMapper.selectByExample(new UserDimensionValueExample());
        } else if (!StringUtils.hasText(dimensionId) && StringUtils.hasText(dimensionValueId)) {
            userRoleUserRoleDimensionList = findUserDimensionValueByDimensionIdAndDimensionValueId(null,
                    dimensionValueId);
        } else if (StringUtils.hasText(dimensionId) && !StringUtils.hasText(dimensionValueId)) {
            userRoleUserRoleDimensionList = findUserDimensionValueByDimensionIdAndDimensionValueId(dimensionId, null);
        } else {
            userRoleUserRoleDimensionList = findUserDimensionValueByDimensionIdAndDimensionValueId(dimensionId,
                    dimensionValueId);
        }
        return userRoleUserRoleDimensionList;
    }

    private List<UserDimensionValue> findUserDimensionValueByDimensionIdAndDimensionValueId(String dimensionId,
                                                                                            String dimensionValueId) {
        UserDimensionValueExample userDimensionValueExample = new UserDimensionValueExample();
        pwc.taxtech.atms.entity.UserDimensionValueExample.Criteria criteria = userDimensionValueExample
                .createCriteria();
        if (dimensionId != null) {
            criteria.andDimensionIdEqualTo(dimensionId);
        }
        if (dimensionValueId != null) {
            criteria.andDimensionValueIdEqualTo(dimensionValueId);
        }
        return userDimensionValueMapper.selectByExample(userDimensionValueExample);
    }

    public List<DimensionUser> getDimensionUserRoleList(String dimensionId, String dimensionValueId) {
        List<DimensionUser> retList = new ArrayList<>();
        if (!DimensionConstant.OrgSubChildrenId.equals(dimensionId)) {
            List<VMUser> userList = userMapper.selectByExample(new UserExample()).stream().map(this::rotateUserToVMUser)
                    .collect(Collectors.toList());
            List<UserRoleInfo> result = getAllUserRoleListByUserList(userList, dimensionValueId);
            Dimension dimension = dimensionMapper.selectByPrimaryKey(dimensionId);
            DimensionValue dimensionValue = dimensionValueMapper.selectByIdIgnoreCase(dimensionValueId);
            String dimensionName = dimension == null ? "" : dimension.getName();
            String dimensionValueName = dimensionValue == null ? "" : dimensionValue.getName();
            retList = parseDimensionUserList(result, dimensionId, dimensionName, dimensionValueId, dimensionValueName);
        } else {
            UserRoleDimensionValueDto userRoleDimensionValueDto = new UserRoleDimensionValueDto();
            userRoleDimensionValueDto.setOrganizationId(dimensionValueId);
            List<UserRoleInfo> userRoleInfoList = getUserRoleList(userRoleDimensionValueDto);
            userRoleInfoList = userRoleInfoList.stream().filter(sa -> BooleanUtils.isTrue(sa.getIsAccessible()))
                    .collect(Collectors.toList());
            for (UserRoleInfo item : userRoleInfoList) {
                DimensionUser dimensionUser = new DimensionUser();
                dimensionUser.setDimensionId(dimensionId);
                dimensionUser.setDimensionValueId(dimensionValueId);
                dimensionUser.setUserId(item.getId());
                dimensionUser.setUserName(item.getUserName());
                dimensionUser.setRoleList(item.getRoleInfoList().stream()
                        .map(p -> generateNameDto(p.getId(), p.getName())).distinct().collect(Collectors.toList()));
                dimensionUser.setOrgList(userRoleInfoList.stream().filter(p -> Objects.equals(p.getId(), item.getId()))
                        .map(p -> generateNameDto(p.getOrganizationId(), p.getOrganizationName())).distinct()
                        .collect(Collectors.toList()));
                retList.add(dimensionUser);
            }
        }
        return retList;
    }

    private List<DimensionUser> parseDimensionUserList(List<UserRoleInfo> result, String dimensionId,
                                                       String dimensionName, String dimensionValueId, String dimensionValueName) {
        List<DimensionUser> retList = new ArrayList<>();
        List<String> userIdList = result.stream().map(UserRoleInfo::getId).distinct().collect(Collectors.toList());
        for (String userId : userIdList) {
            List<UserRoleInfo> thisUserList = result.stream().filter(sa -> Objects.equals(sa.getId(), userId))
                    .collect(Collectors.toList());
            UserRoleInfo first = thisUserList.stream().findFirst().orElse(new UserRoleInfo());
            DimensionUser user = new DimensionUser();
            user.setOrgList(new ArrayList<>());
            user.setDimensionId(dimensionId);
            user.setDimensionValueId(dimensionValueId);
            user.setDimensionName(dimensionName);
            user.setDimensionValueName(dimensionValueName);
            user.setHasOriginalRole(true);
            user.setId(userId);
            user.setIsAccessible(true);
            user.setIsHeritable(true);
            user.setRoleList(new ArrayList<>());
            user.setUserId(userId);
            user.setUserName(first.getUserName());
            user.setOrgList(
                    thisUserList.stream().map(s -> generateNameDto(s.getOrganizationId(), s.getOrganizationName()))
                            .collect(Collectors.toList()));
            for (UserRoleInfo thisUser : thisUserList) {
                List<NameDto> thisUserRoleList = thisUser.getRoleInfoList().stream()
                        .map(sa -> generateNameDto(sa.getId(), sa.getName())).collect(Collectors.toList());
                user.getRoleList().addAll(thisUserRoleList);
            }
            user.setRoleList(user.getRoleList().stream().map(sa -> generateNameDto(sa.getId(), sa.getName())).distinct()
                    .collect(Collectors.toList()));
            retList.add(user);
        }
        return retList;
    }

    private NameDto generateNameDto(String id, String name) {
        NameDto nameDto = new NameDto();
        nameDto.setName(name);
        nameDto.setId(id);
        return nameDto;
    }

    public List<UserRoleInfo> getActiveUserRoleListByAreaId(String areaId) {
        // 用户列表
        UserExample userExample = new UserExample();
        userExample.createCriteria().andStatusNotEqualTo(0);
        List<VMUser> userList = userMapper.selectByExample(userExample).stream()
                .map(sa -> CommonUtils.copyProperties(sa, new VMUser())).collect(toList());
        // 角色列表
        List<NameDto> roleList = roleMapper.selectByExample(new RoleExample()).stream()
                .map(sa -> CommonUtils.copyProperties(sa, new NameDto())).collect(toList());
        // 获取原始角色列表
        List<UserRoleSimpleDto> userRoleList = getOriginalUserRoleList(roleList);
        // 用户维度
        UserDimensionValueExample userDimensionValueExample = new UserDimensionValueExample();
        userDimensionValueExample.createCriteria().andDimensionValueIdEqualTo(areaId);
        List<UserDimensionValue> userDimensionValueList = userDimensionValueMapper
                .selectByExample(userDimensionValueExample);
        // 不继承的维度列表
        UserDimensionValueOrgExample userDimensionValueOrgExample = new UserDimensionValueOrgExample();
        userDimensionValueOrgExample.createCriteria().andIsHeritableEqualTo(CommonConstants.IsNotHeritable);
        List<UserDimensionValueOrg> notuserDimensionValueOrg = userDimensionValueOrgMapper
                .selectByExample(userDimensionValueOrgExample);
        // 维度角色列表
        List<UserDimensionValueRoleDto> dimensionValueRoleList = getDimensionValueRoleList(roleList);
        // 用户机构
        List<UserOrganization> userOrganizationList = userOrganizationMapper
                .selectByExample(new UserOrganizationExample());
        // 机构角色列表
        List<UserOrganizationRoleDto> userOrganizationRoleList = getUserOrganizationRoleList(roleList);
        // 机构列表
        OrganizationExample organizationExample = new OrganizationExample();
        organizationExample.createCriteria().andAreaIdEqualTo(areaId);
        List<OrganizationDto> organizationList = organizationMapper.selectByExample(organizationExample).stream()
                .map(sa -> CommonUtils.copyProperties(sa, new OrganizationDto())).collect(toList());
        // 机构维度设置列表
        List<DimensionValueOrgDto> dimensionValueOrgList = getDimensionValueOrgDtoList();

        List<UserRoleInfo> retList = new ArrayList<>();
        for (OrganizationDto orgInfo : organizationList) {
            List<UserOrganization> thisUserOrganizationList = userOrganizationList.stream()
                    .filter(sa -> Objects.equals(sa.getOrganizationId(), orgInfo.getId())).collect(toList());
            List<DimensionValueOrgDto> thisDimensionValueOrgList = dimensionValueOrgList.stream()
                    .filter(sa -> Objects.equals(sa.getOrganizationId(), orgInfo.getId())).collect(toList());
            // 用户维度关联表,排除不继承的关联
            List<UserDimensionValue> thisUserDimensionValueList = userDimensionValueList
                    .stream().filter(
                            p -> notuserDimensionValueOrg.stream()
                                    .noneMatch(sa -> Objects.equals(sa.getOrganizationId(), orgInfo.getId())
                                            && Objects.equals(sa.getUserDimensionValueId(), p.getId())))
                    .collect(toList());
            List<UserRoleInfo> orgUserInfoList = getUserRoleInfoListByOrg(thisUserOrganizationList, orgInfo, userList,
                    userRoleList, thisUserDimensionValueList, thisDimensionValueOrgList, userOrganizationRoleList,
                    dimensionValueRoleList);
            if (!orgUserInfoList.isEmpty()) {
                retList.addAll(orgUserInfoList);
            }
        }
        return retList;
    }

}