|
|
|
@ -17,32 +17,35 @@ |
|
|
|
|
|
|
|
package com.elink.esua.epdc.modules.category.service.impl; |
|
|
|
|
|
|
|
import cn.afterturn.easypoi.excel.ExcelImportUtil; |
|
|
|
import cn.afterturn.easypoi.excel.entity.ImportParams; |
|
|
|
import com.alibaba.fastjson.JSON; |
|
|
|
import com.alibaba.fastjson.JSONArray; |
|
|
|
import com.alibaba.fastjson.JSONObject; |
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
|
|
|
import com.baomidou.mybatisplus.core.metadata.IPage; |
|
|
|
import com.elink.esua.epdc.commons.mybatis.service.impl.BaseServiceImpl; |
|
|
|
import com.elink.esua.epdc.commons.tools.constant.Constant; |
|
|
|
import com.elink.esua.epdc.commons.tools.constant.NumConstant; |
|
|
|
import com.elink.esua.epdc.commons.tools.exception.ErrorCode; |
|
|
|
import com.elink.esua.epdc.commons.tools.exception.RenException; |
|
|
|
import com.elink.esua.epdc.commons.tools.page.PageData; |
|
|
|
import com.elink.esua.epdc.commons.tools.redis.RedisKeys; |
|
|
|
import com.elink.esua.epdc.commons.tools.redis.RedisUtils; |
|
|
|
import com.elink.esua.epdc.commons.tools.utils.ConvertUtils; |
|
|
|
import com.elink.esua.epdc.commons.tools.constant.FieldConstant; |
|
|
|
import com.elink.esua.epdc.commons.tools.utils.Result; |
|
|
|
import com.elink.esua.epdc.commons.tools.utils.TreeUtils; |
|
|
|
import com.elink.esua.epdc.dto.category.CategoryDTO; |
|
|
|
import com.elink.esua.epdc.dto.category.CategoryOption; |
|
|
|
import com.elink.esua.epdc.dto.category.CategoryTreeDTO; |
|
|
|
import com.elink.esua.epdc.modules.category.dao.CategoryDao; |
|
|
|
import com.elink.esua.epdc.modules.category.entity.CategoryEntity; |
|
|
|
import com.elink.esua.epdc.modules.category.redis.CategoryRedis; |
|
|
|
import com.elink.esua.epdc.modules.category.service.CategoryService; |
|
|
|
import com.google.common.collect.Lists; |
|
|
|
import org.apache.commons.lang3.StringUtils; |
|
|
|
import org.slf4j.Logger; |
|
|
|
import org.slf4j.LoggerFactory; |
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
import org.springframework.transaction.annotation.Transactional; |
|
|
|
import org.springframework.web.multipart.MultipartFile; |
|
|
|
|
|
|
|
import java.io.File; |
|
|
|
import java.util.*; |
|
|
|
|
|
|
|
/** |
|
|
|
@ -54,173 +57,291 @@ import java.util.*; |
|
|
|
@Service |
|
|
|
public class CategoryServiceImpl extends BaseServiceImpl<CategoryDao, CategoryEntity> implements CategoryService { |
|
|
|
|
|
|
|
@Autowired |
|
|
|
private CategoryRedis categoryRedis; |
|
|
|
|
|
|
|
@Override |
|
|
|
public List<CategoryDTO> list(Map<String, Object> params) { |
|
|
|
List<CategoryEntity> entityList = baseDao.getList(params); |
|
|
|
|
|
|
|
List<CategoryDTO> dtoList = ConvertUtils.sourceToTarget(entityList, CategoryDTO.class); |
|
|
|
|
|
|
|
return TreeUtils.build(dtoList); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public CategoryDTO get(Long id) { |
|
|
|
if (id == null) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
CategoryEntity entity = baseDao.getById(id); |
|
|
|
|
|
|
|
return ConvertUtils.sourceToTarget(entity, CategoryDTO.class); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public void save(CategoryDTO dto) { |
|
|
|
String categoryCode = dto.getCategoryCode(); |
|
|
|
if (StringUtils.isNotBlank(categoryCode)) { |
|
|
|
if (getCodeCount(dto) > 0) { |
|
|
|
throw new RenException("您输入的编码已存在"); |
|
|
|
} |
|
|
|
} |
|
|
|
CategoryEntity entity = ConvertUtils.sourceToTarget(dto, CategoryEntity.class); |
|
|
|
List<CategoryEntity> list = getPidListByPid(entity.getPid()); |
|
|
|
if (list.size() == 0){ |
|
|
|
entity.setPids("0"); |
|
|
|
}else { |
|
|
|
String pids = ""; |
|
|
|
for (int i = 0; i < list.size(); i++){ |
|
|
|
if (i == list.size() -1){ |
|
|
|
pids = pids + list.get(i).getId().toString(); |
|
|
|
}else { |
|
|
|
pids = pids + list.get(i).getId().toString() + ","; |
|
|
|
} |
|
|
|
} |
|
|
|
entity.setPids(pids); |
|
|
|
} |
|
|
|
insert(entity); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public List<CategoryEntity> getPidListById(Long id) { |
|
|
|
//所有的分类列表
|
|
|
|
CategoryEntity categoryEntity = baseDao.selectById(id); |
|
|
|
return getPidListByPid(categoryEntity.getPid()); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取所有上级分类 |
|
|
|
* |
|
|
|
* @param pid 上级ID |
|
|
|
*/ |
|
|
|
private List<CategoryEntity> getPidListByPid(Long pid) { |
|
|
|
//顶级部门,无上级部门
|
|
|
|
if (Constant.CATEGORY_ROOT.equals(pid)) { |
|
|
|
return new ArrayList<>(); |
|
|
|
} |
|
|
|
|
|
|
|
//所有的分类列表
|
|
|
|
QueryWrapper<CategoryEntity> wrapper = new QueryWrapper<>(); |
|
|
|
List<CategoryEntity> categoryEntityList = baseDao.selectList(wrapper); |
|
|
|
|
|
|
|
//list转map
|
|
|
|
Map<Long, CategoryEntity> map = new HashMap<>(categoryEntityList.size()); |
|
|
|
for (CategoryEntity entity : categoryEntityList) { |
|
|
|
map.put(entity.getId(), entity); |
|
|
|
} |
|
|
|
|
|
|
|
//递归查询所有上级分类列表
|
|
|
|
List<CategoryEntity> pCategoryEntityList = new ArrayList<>(); |
|
|
|
|
|
|
|
getPidTree(pid, map, pCategoryEntityList); |
|
|
|
|
|
|
|
return pCategoryEntityList; |
|
|
|
} |
|
|
|
|
|
|
|
private void getPidTree(Long pid, Map<Long, CategoryEntity> map, List<CategoryEntity> pCategoryEntityList) { |
|
|
|
//顶级,无上级
|
|
|
|
if (Constant.CATEGORY_ROOT.equals(pid)) { |
|
|
|
return; |
|
|
|
} |
|
|
|
//上级存在
|
|
|
|
CategoryEntity parent = map.get(pid); |
|
|
|
if (parent != null) { |
|
|
|
getPidTree(parent.getPid(), map, pCategoryEntityList); |
|
|
|
} |
|
|
|
|
|
|
|
pCategoryEntityList.add(parent); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public Integer getCodeCount(CategoryDTO dto) { |
|
|
|
QueryWrapper<CategoryEntity> wrapper = new QueryWrapper<>(); |
|
|
|
wrapper.eq("category_code", dto.getCategoryCode()); |
|
|
|
Long id = dto.getId(); |
|
|
|
wrapper.ne(id!=null, "id", dto.getId()); |
|
|
|
wrapper.eq("del_flag","0"); |
|
|
|
return baseDao.selectCount(wrapper); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public void update(CategoryDTO dto) { |
|
|
|
String categoryCode = dto.getCategoryCode(); |
|
|
|
if (StringUtils.isNotBlank(categoryCode)) { |
|
|
|
if (getCodeCount(dto) > 0) { |
|
|
|
throw new RenException("您输入的编码已存在"); |
|
|
|
} |
|
|
|
} |
|
|
|
CategoryEntity entity = ConvertUtils.sourceToTarget(dto, CategoryEntity.class); |
|
|
|
//上级部门不能为自身
|
|
|
|
if (entity.getId().equals(entity.getPid())) { |
|
|
|
throw new RenException(ErrorCode.SUPERIOR_DEPT_ERROR); |
|
|
|
} |
|
|
|
List<CategoryEntity> list = getPidListByPid(entity.getPid()); |
|
|
|
if (list.size() == 0){ |
|
|
|
entity.setPids("0"); |
|
|
|
}else { |
|
|
|
String pids = ""; |
|
|
|
for (int i = 0; i < list.size(); i++){ |
|
|
|
if (i == list.size() -1){ |
|
|
|
pids = pids + list.get(i).getId().toString(); |
|
|
|
}else { |
|
|
|
pids = pids + list.get(i).getId().toString() + ","; |
|
|
|
} |
|
|
|
} |
|
|
|
entity.setPids(pids); |
|
|
|
} |
|
|
|
updateById(entity); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public void delete(Long id) { |
|
|
|
//判断是否有子部门
|
|
|
|
List<Long> subList = getSubCategoryIdList(id); |
|
|
|
if (subList.size() > 1) { |
|
|
|
throw new RenException(ErrorCode.DEPT_SUB_DELETE_ERROR); |
|
|
|
} |
|
|
|
baseDao.deleteBatchIds(Arrays.asList(new Long[]{id})); |
|
|
|
|
|
|
|
// 逻辑删除(@TableLogic 注解)
|
|
|
|
//logicDelete(new Long[]{id}, CategoryEntity.class);
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public List<Long> getSubCategoryIdList(Long id) { |
|
|
|
List<Long> subCategoryIdList = baseDao.getSubCategoryIdList("%" + id + "%"); |
|
|
|
subCategoryIdList.add(id); |
|
|
|
return subCategoryIdList; |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public Result insertPartyList(MultipartFile file) { |
|
|
|
|
|
|
|
return new Result(); |
|
|
|
} |
|
|
|
@Autowired |
|
|
|
private CategoryRedis categoryRedis; |
|
|
|
@Autowired |
|
|
|
private RedisUtils redisUtils; |
|
|
|
|
|
|
|
private Logger logger = LoggerFactory.getLogger(getClass()); |
|
|
|
|
|
|
|
@Override |
|
|
|
public List<CategoryDTO> list(Map<String, Object> params) { |
|
|
|
List<CategoryEntity> entityList = baseDao.getList(params); |
|
|
|
|
|
|
|
List<CategoryDTO> dtoList = ConvertUtils.sourceToTarget(entityList, CategoryDTO.class); |
|
|
|
|
|
|
|
return TreeUtils.build(dtoList); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public CategoryDTO get(Long id) { |
|
|
|
if (id == null) { |
|
|
|
return null; |
|
|
|
} |
|
|
|
CategoryEntity entity = baseDao.getById(id); |
|
|
|
|
|
|
|
return ConvertUtils.sourceToTarget(entity, CategoryDTO.class); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public void save(CategoryDTO dto) { |
|
|
|
String categoryCode = dto.getCategoryCode(); |
|
|
|
if (StringUtils.isNotBlank(categoryCode)) { |
|
|
|
if (getCodeCount(dto) > 0) { |
|
|
|
throw new RenException("您输入的编码已存在"); |
|
|
|
} |
|
|
|
} |
|
|
|
CategoryEntity entity = ConvertUtils.sourceToTarget(dto, CategoryEntity.class); |
|
|
|
List<CategoryEntity> list = getPidListByPid(entity.getPid()); |
|
|
|
if (list.size() == 0) { |
|
|
|
entity.setPids("0"); |
|
|
|
} else { |
|
|
|
String pids = ""; |
|
|
|
for (int i = 0; i < list.size(); i++) { |
|
|
|
if (i == list.size() - 1) { |
|
|
|
pids = pids + list.get(i).getId().toString(); |
|
|
|
} else { |
|
|
|
pids = pids + list.get(i).getId().toString() + ","; |
|
|
|
} |
|
|
|
} |
|
|
|
entity.setPids(pids); |
|
|
|
} |
|
|
|
insert(entity); |
|
|
|
this.packageCategoryOption(); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public List<CategoryEntity> getPidListById(Long id) { |
|
|
|
//所有的分类列表
|
|
|
|
CategoryEntity categoryEntity = baseDao.selectById(id); |
|
|
|
return getPidListByPid(categoryEntity.getPid()); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 获取所有上级分类 |
|
|
|
* |
|
|
|
* @param pid 上级ID |
|
|
|
*/ |
|
|
|
private List<CategoryEntity> getPidListByPid(Long pid) { |
|
|
|
//顶级部门,无上级部门
|
|
|
|
if (Constant.CATEGORY_ROOT.equals(pid)) { |
|
|
|
return new ArrayList<>(); |
|
|
|
} |
|
|
|
|
|
|
|
//所有的分类列表
|
|
|
|
QueryWrapper<CategoryEntity> wrapper = new QueryWrapper<>(); |
|
|
|
List<CategoryEntity> categoryEntityList = baseDao.selectList(wrapper); |
|
|
|
|
|
|
|
//list转map
|
|
|
|
Map<Long, CategoryEntity> map = new HashMap<>(categoryEntityList.size()); |
|
|
|
for (CategoryEntity entity : categoryEntityList) { |
|
|
|
map.put(entity.getId(), entity); |
|
|
|
} |
|
|
|
|
|
|
|
//递归查询所有上级分类列表
|
|
|
|
List<CategoryEntity> pCategoryEntityList = new ArrayList<>(); |
|
|
|
|
|
|
|
getPidTree(pid, map, pCategoryEntityList); |
|
|
|
|
|
|
|
return pCategoryEntityList; |
|
|
|
} |
|
|
|
|
|
|
|
private void getPidTree(Long pid, Map<Long, CategoryEntity> map, List<CategoryEntity> pCategoryEntityList) { |
|
|
|
//顶级,无上级
|
|
|
|
if (Constant.CATEGORY_ROOT.equals(pid)) { |
|
|
|
return; |
|
|
|
} |
|
|
|
//上级存在
|
|
|
|
CategoryEntity parent = map.get(pid); |
|
|
|
if (parent != null) { |
|
|
|
getPidTree(parent.getPid(), map, pCategoryEntityList); |
|
|
|
} |
|
|
|
|
|
|
|
pCategoryEntityList.add(parent); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public Integer getCodeCount(CategoryDTO dto) { |
|
|
|
QueryWrapper<CategoryEntity> wrapper = new QueryWrapper<>(); |
|
|
|
wrapper.eq("category_code", dto.getCategoryCode()); |
|
|
|
Long id = dto.getId(); |
|
|
|
wrapper.ne(id != null, "id", dto.getId()); |
|
|
|
wrapper.eq("del_flag", "0"); |
|
|
|
return baseDao.selectCount(wrapper); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public void update(CategoryDTO dto) { |
|
|
|
String categoryCode = dto.getCategoryCode(); |
|
|
|
if (StringUtils.isNotBlank(categoryCode)) { |
|
|
|
if (getCodeCount(dto) > 0) { |
|
|
|
throw new RenException("您输入的编码已存在"); |
|
|
|
} |
|
|
|
} |
|
|
|
CategoryEntity entity = ConvertUtils.sourceToTarget(dto, CategoryEntity.class); |
|
|
|
//上级部门不能为自身
|
|
|
|
if (entity.getId().equals(entity.getPid())) { |
|
|
|
throw new RenException(ErrorCode.SUPERIOR_DEPT_ERROR); |
|
|
|
} |
|
|
|
List<CategoryEntity> list = getPidListByPid(entity.getPid()); |
|
|
|
if (list.size() == 0) { |
|
|
|
entity.setPids("0"); |
|
|
|
} else { |
|
|
|
String pids = ""; |
|
|
|
for (int i = 0; i < list.size(); i++) { |
|
|
|
if (i == list.size() - 1) { |
|
|
|
pids = pids + list.get(i).getId().toString(); |
|
|
|
} else { |
|
|
|
pids = pids + list.get(i).getId().toString() + ","; |
|
|
|
} |
|
|
|
} |
|
|
|
entity.setPids(pids); |
|
|
|
} |
|
|
|
updateById(entity); |
|
|
|
this.packageCategoryOption(); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
@Transactional(rollbackFor = Exception.class) |
|
|
|
public void delete(Long id) { |
|
|
|
//判断是否有子部门
|
|
|
|
List<Long> subList = getSubCategoryIdList(id); |
|
|
|
if (subList.size() > 1) { |
|
|
|
throw new RenException(ErrorCode.DEPT_SUB_DELETE_ERROR); |
|
|
|
} |
|
|
|
baseDao.deleteBatchIds(Arrays.asList(new Long[]{id})); |
|
|
|
|
|
|
|
// 逻辑删除(@TableLogic 注解)
|
|
|
|
//logicDelete(new Long[]{id}, CategoryEntity.class);
|
|
|
|
this.packageCategoryOption(); |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public List<Long> getSubCategoryIdList(Long id) { |
|
|
|
List<Long> subCategoryIdList = baseDao.getSubCategoryIdList("%" + id + "%"); |
|
|
|
subCategoryIdList.add(id); |
|
|
|
return subCategoryIdList; |
|
|
|
} |
|
|
|
|
|
|
|
@Override |
|
|
|
public Result insertPartyList(MultipartFile file) { |
|
|
|
|
|
|
|
return new Result(); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @param |
|
|
|
* @return com.elink.esua.epdc.commons.tools.utils.Result |
|
|
|
* @Author yinzuomei |
|
|
|
* @Description 查询事件类别树, 供下拉框调用 |
|
|
|
* @Date 2019/12/3 18:07 |
|
|
|
**/ |
|
|
|
@Override |
|
|
|
public Result<CategoryOption> getCategoryTree() { |
|
|
|
String eventsCategoryKey = RedisKeys.getEventsCategoryKey(); |
|
|
|
Object obj = redisUtils.get(eventsCategoryKey); |
|
|
|
if (null == obj) { |
|
|
|
this.packageCategoryOption(); |
|
|
|
obj = redisUtils.get(eventsCategoryKey); |
|
|
|
} |
|
|
|
return new Result<CategoryOption>().ok((CategoryOption) obj); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* @param |
|
|
|
* @return void |
|
|
|
* @Author yinzuomei |
|
|
|
* @Description 组装事件类别 |
|
|
|
* @Date 2019/12/3 18:18 |
|
|
|
**/ |
|
|
|
@Override |
|
|
|
public void packageCategoryOption() { |
|
|
|
List<CategoryTreeDTO> dtoList = baseDao.selectListCategoryTreeDTO(); |
|
|
|
JSONObject node; |
|
|
|
JSONArray headNodes = new JSONArray(); |
|
|
|
for (CategoryTreeDTO categoryTreeDto : dtoList) { |
|
|
|
|
|
|
|
if (categoryTreeDto.getPid().longValue() == NumConstant.ZERO_L) { |
|
|
|
node = new JSONObject(); |
|
|
|
node.put("value", categoryTreeDto.getId()); |
|
|
|
node.put("label", categoryTreeDto.getCategoryName()); |
|
|
|
headNodes.add(node); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 用于存放所有父级节点
|
|
|
|
JSONArray parent; |
|
|
|
// 用于存放所有子级节点
|
|
|
|
JSONArray allChildren = new JSONArray(); |
|
|
|
JSONArray children; |
|
|
|
// 用于存放单个子级节点
|
|
|
|
JSONObject childNode; |
|
|
|
|
|
|
|
parent = headNodes; |
|
|
|
// 存放其余未处理的类别(节点)
|
|
|
|
List<CategoryTreeDTO> others = this.getOtherCategory(dtoList, parent); |
|
|
|
|
|
|
|
while (!others.isEmpty()) { |
|
|
|
for (int i = 0; i < parent.size(); i++) { |
|
|
|
node = parent.getJSONObject(i); |
|
|
|
children = new JSONArray(); |
|
|
|
for (CategoryTreeDTO categoryTreeDto : others) { |
|
|
|
if (categoryTreeDto.getPid().equals(node.get("value"))) { |
|
|
|
childNode = new JSONObject(); |
|
|
|
childNode.put("value", categoryTreeDto.getId()); |
|
|
|
childNode.put("label", categoryTreeDto.getCategoryName()); |
|
|
|
|
|
|
|
children.add(childNode); |
|
|
|
allChildren.add(childNode); |
|
|
|
} |
|
|
|
} |
|
|
|
if (!children.isEmpty()) { |
|
|
|
node.put("children", children); |
|
|
|
} |
|
|
|
} |
|
|
|
parent = allChildren; |
|
|
|
|
|
|
|
others = this.getOtherCategory(others, parent); |
|
|
|
|
|
|
|
} |
|
|
|
// JSONObject treeNodes = new JSONObject();
|
|
|
|
// treeNodes.put("options", headNodes);
|
|
|
|
// logger.info(treeNodes.toJSONString());
|
|
|
|
//存放到redis中
|
|
|
|
List<JSONArray> cache = Lists.newArrayList(); |
|
|
|
cache.add(headNodes); |
|
|
|
CategoryOption option = new CategoryOption(); |
|
|
|
option.setOptions(cache.get(0)); |
|
|
|
redisUtils.set(RedisKeys.getEventsCategoryKey(), option); |
|
|
|
} |
|
|
|
|
|
|
|
/* |
|
|
|
* @param dtoList 上次进行筛选的分类集合 |
|
|
|
* @param parent 已处理过的上级节点 |
|
|
|
* @return java.util.List<com.elink.esua.epdc.dto.category.CategoryTreeDTO> |
|
|
|
* @Author yinzuomei |
|
|
|
* @Description 组装其余未处理过的分类集合 |
|
|
|
* @Date 2019/12/3 17:27 |
|
|
|
**/ |
|
|
|
private List<CategoryTreeDTO> getOtherCategory(List<CategoryTreeDTO> dtoList, JSONArray parent) { |
|
|
|
List<Long> already = Lists.newArrayList(); |
|
|
|
for (int i = 0; i < parent.size(); i++) { |
|
|
|
already.add((Long) parent.getJSONObject(i).get("value")); |
|
|
|
} |
|
|
|
|
|
|
|
List<CategoryTreeDTO> others = Lists.newArrayList(); |
|
|
|
|
|
|
|
for (CategoryTreeDTO categoryTreeDto : dtoList) { |
|
|
|
Long categoryTreeDtoId = categoryTreeDto.getId(); |
|
|
|
if (!already.contains(categoryTreeDtoId)) { |
|
|
|
others.add(categoryTreeDto); |
|
|
|
} |
|
|
|
} |
|
|
|
return others; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|