From f8b9a8cec961040962f35a16b00580ca3adacf29 Mon Sep 17 00:00:00 2001 From: ty <1577900710@qq.com> Date: Wed, 3 Jan 2024 16:35:53 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AE=9A=E6=97=B6=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=EF=BC=9A=E8=AF=81=E4=B9=A6=E5=88=B0=E6=9C=9F=E6=8F=90?= =?UTF-8?q?=E9=86=92?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../scheduled/mapper/basic/CertificatetMapper.xml | 6 - .../mapper/basic/CertificatetNoticeMapper.xml | 6 - .../mapper/basic/PersonManagemetMapper.xml | 97 -------------- .../scheduled/scheduled/BasicScheduledTask.java | 148 +++++++++++++++++++++ .../scheduled/scheduled/basicScheduledTask.java | 141 -------------------- .../service/basic/IImsPresonManagementService.java | 21 +++ .../basic/impl/CertificatetNoticeServiceImpl.java | 2 + .../basic/impl/CertificatetServiceImpl.java | 2 + .../basic/impl/PresonManagementServiceImpl.java | 27 ++++ .../resources/mapper/basic/CertificatetMapper.xml | 6 + .../mapper/basic/CertificatetNoticeMapper.xml | 6 + .../mapper/basic/PersonManagemetMapper.xml | 97 ++++++++++++++ 12 files changed, 309 insertions(+), 250 deletions(-) delete mode 100644 hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/mapper/basic/CertificatetMapper.xml delete mode 100644 hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/mapper/basic/CertificatetNoticeMapper.xml delete mode 100644 hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/mapper/basic/PersonManagemetMapper.xml create mode 100644 hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/scheduled/BasicScheduledTask.java delete mode 100644 hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/scheduled/basicScheduledTask.java create mode 100644 hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/IImsPresonManagementService.java create mode 100644 hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/impl/PresonManagementServiceImpl.java create mode 100644 hzims-service/hzims-scheduled/src/main/resources/mapper/basic/CertificatetMapper.xml create mode 100644 hzims-service/hzims-scheduled/src/main/resources/mapper/basic/CertificatetNoticeMapper.xml create mode 100644 hzims-service/hzims-scheduled/src/main/resources/mapper/basic/PersonManagemetMapper.xml diff --git a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/mapper/basic/CertificatetMapper.xml b/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/mapper/basic/CertificatetMapper.xml deleted file mode 100644 index 6941d55..0000000 --- a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/mapper/basic/CertificatetMapper.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/mapper/basic/CertificatetNoticeMapper.xml b/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/mapper/basic/CertificatetNoticeMapper.xml deleted file mode 100644 index c951079..0000000 --- a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/mapper/basic/CertificatetNoticeMapper.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/mapper/basic/PersonManagemetMapper.xml b/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/mapper/basic/PersonManagemetMapper.xml deleted file mode 100644 index 409cbfb..0000000 --- a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/mapper/basic/PersonManagemetMapper.xml +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/scheduled/BasicScheduledTask.java b/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/scheduled/BasicScheduledTask.java new file mode 100644 index 0000000..843c270 --- /dev/null +++ b/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/scheduled/BasicScheduledTask.java @@ -0,0 +1,148 @@ +package com.hnac.hzims.scheduled.scheduled; + +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.hnac.hzims.basic.entity.CertificatetEntity; +import com.hnac.hzims.basic.entity.CertificatetNoticeEntity; +import com.hnac.hzims.basic.entity.PersonManagemetEntity; +import com.hnac.hzims.message.MessageConstants; +import com.hnac.hzims.message.dto.BusinessMessageDTO; +import com.hnac.hzims.message.entity.config.SmsConfigEntity; +import com.hnac.hzims.message.fegin.IMessageClient; +import com.hnac.hzims.message.fegin.IMessageConfigClient; +import com.hnac.hzims.scheduled.mapper.basic.PersonManagemetMapper; +import com.hnac.hzims.scheduled.service.basic.IImsCertificatetNoticeService; +import com.hnac.hzims.scheduled.service.basic.IImsCertificatetService; +import com.hnac.hzims.scheduled.service.basic.IImsPresonManagementService; +import com.xxl.job.core.biz.model.ReturnT; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang.StringUtils; +import org.junit.jupiter.api.Test; +import org.springblade.core.tool.api.R; +import org.springblade.core.tool.utils.CollectionUtil; +import org.springblade.core.tool.utils.DateUtil; +import org.springblade.core.tool.utils.ObjectUtil; +import org.springblade.system.feign.ISysClient; +import org.springblade.system.user.cache.UserCache; +import org.springblade.system.user.entity.User; +import org.springblade.system.user.feign.IUserClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.stream.Collectors; + + +/** + * 排班到期定时任务通知 + * + * @author ty + */ +@Slf4j +@Component +public class BasicScheduledTask { + + @Autowired + private IImsCertificatetService iImsCertificatetService; + @Autowired + private IImsCertificatetNoticeService iImsCertificatetNoticeService; + @Autowired + private ISysClient sysClient; + @Autowired + private IUserClient userClient; + @Autowired + private IMessageClient messageClient; + @Autowired + private IImsPresonManagementService presonManagementService; + @Autowired + private IMessageConfigClient messageConfigClient; + + /** + * realId刷新 + */ +// @XxlJob(CERTIFICATET_DEAD_LINE_NOTICE) + @Scheduled(cron = "0/40 * * * * ? ") +// public ReturnT certificatetDeadLineNotice(String param) throws ParseException { + public ReturnT certificatetDeadLineNotice() throws ParseException { + Date endTime = new Date(); + String param=""; + if (StringUtils.isNotBlank(param)) { + endTime = new SimpleDateFormat("yyyy-MM-dd").parse(param); + } + CertificatetNoticeEntity noticeEntity = iImsCertificatetNoticeService.getOne(Wrappers.lambdaQuery() + .eq(CertificatetNoticeEntity::getIsDeleted, 0) + .last("limit 1;")); + //用户档案过期截止时间 + Date date = DateUtil.plusDays(endTime, noticeEntity.getSafeTime()); + List list = iImsCertificatetService.list(Wrappers.lambdaQuery() + .le(CertificatetEntity::getDeadTime, date)); + String noticeUsers = noticeEntity.getNoticeUsers(); + List userList = Arrays.asList(noticeUsers.split(",")); + if (CollectionUtil.isNotEmpty(userList) && CollectionUtil.isNotEmpty(list)) { + List personIds = list.stream().map(CertificatetEntity::getPersonId).collect(Collectors.toList()); + List personManagemetEntities = presonManagementService.list(Wrappers.query().lambda().in(PersonManagemetEntity::getId, personIds)); + String personNotice=""; + if (CollectionUtil.isNotEmpty(personManagemetEntities)) { + personNotice = personManagemetEntities.stream().map(PersonManagemetEntity::getName).collect(Collectors.joining(",")); + } + if ("1".equals(noticeEntity.getSendType())) { + sendSmsByUserList(userList, date,personNotice); + } + sendMessage(list.get(0), noticeEntity.getSafeTime(), noticeEntity.getNoticeUsers(),personNotice); + } + return new ReturnT<>("SUCCESS"); + } + + @Test + public void getVideoMonitor() throws ParseException { + ReturnT stringReturnT = this.certificatetDeadLineNotice(); + } + + private void sendSmsByUserList(List userList, Date date,String personNotice) { + //区分用户 + for (String s : userList) { + User user = UserCache.getUser(Long.valueOf(s)); + String phone = ""; + if (ObjectUtil.isNotEmpty(user)) { + phone = user.getPhone(); + } + //短信推送 + String code = "certificatetNotice"; + SmsConfigEntity smsConfigEntity = messageConfigClient.getSmsConfigByBusinessKey(code); + Map contentParams = new HashMap<>(2); + contentParams.put("one", personNotice); + String deadLine = DateUtil.format(date, "yyyy-MM-dd"); + contentParams.put("two", deadLine); + smsConfigEntity.setTemplateParam(JSONObject.toJSONString(contentParams)); + smsConfigEntity.setPhones(phone); + messageConfigClient.pushSmsMessageByConfig(smsConfigEntity); + } + } + + private void sendMessage(CertificatetEntity certificatetEntity, Integer date, String users,String personNotice) { +// //注意:通知人是创建人所在机构 + BusinessMessageDTO message = new BusinessMessageDTO(); + message.setBusinessClassify("system"); + message.setBusinessKey(MessageConstants.BusinessClassifyEnum.CERTIFICATETNOTICE.getKey()); + message.setSubject(MessageConstants.BusinessClassifyEnum.CERTIFICATETNOTICE.getDescription()); + message.setTaskId(System.currentTimeMillis()); + message.setTenantId("200000"); + String countent = + personNotice + "的证书即将到期,请提交新的证书资料"; + message.setContent(countent); + message.setDeptId(certificatetEntity.getCreateDept()); + R deptName = sysClient.getDeptName(certificatetEntity.getCreateDept()); + if (deptName.isSuccess()) { + message.setDeptName(deptName.getData()); + } + message.setUserIds(users); + User admin = userClient.userByAccount("200000", "admin").getData(); + message.setCreateUser(admin.getId()); + messageClient.sendAppAndWsMsgByUsers(message); + } + + +} \ No newline at end of file diff --git a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/scheduled/basicScheduledTask.java b/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/scheduled/basicScheduledTask.java deleted file mode 100644 index 9b72730..0000000 --- a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/scheduled/basicScheduledTask.java +++ /dev/null @@ -1,141 +0,0 @@ -package com.hnac.hzims.scheduled.scheduled; - -import com.alibaba.fastjson.JSONObject; -import com.baomidou.mybatisplus.core.toolkit.Wrappers; -import com.hnac.hzims.basic.entity.CertificatetEntity; -import com.hnac.hzims.basic.entity.CertificatetNoticeEntity; -import com.hnac.hzims.basic.entity.PersonManagemetEntity; -import com.hnac.hzims.message.MessageConstants; -import com.hnac.hzims.message.dto.BusinessMessageDTO; -import com.hnac.hzims.message.entity.config.SmsConfigEntity; -import com.hnac.hzims.message.fegin.IMessageClient; -import com.hnac.hzims.message.fegin.IMessageConfigClient; -import com.hnac.hzims.scheduled.mapper.basic.PersonManagemetMapper; -import com.hnac.hzims.scheduled.service.basic.IImsCertificatetNoticeService; -import com.hnac.hzims.scheduled.service.basic.IImsCertificatetService; -import com.xxl.job.core.biz.model.ReturnT; -import com.xxl.job.core.handler.annotation.XxlJob; -import lombok.extern.slf4j.Slf4j; -import org.springblade.core.tool.api.R; -import org.springblade.core.tool.utils.CollectionUtil; -import org.springblade.core.tool.utils.DateUtil; -import org.springblade.core.tool.utils.Func; -import org.springblade.core.tool.utils.ObjectUtil; -import org.springblade.system.feign.ISysClient; -import org.springblade.system.user.cache.UserCache; -import org.springblade.system.user.entity.User; -import org.springblade.system.user.feign.IUserClient; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; -import java.util.stream.Collectors; - -import static com.hnac.hzims.operational.main.constant.MainConstants.*; - - -/** - * 排班到期定时任务通知 - * - * @author ty - */ -@Slf4j -@Component -public class basicScheduledTask { - - @Autowired - private IImsCertificatetService iImsCertificatetService; - @Autowired - private IImsCertificatetNoticeService iImsCertificatetNoticeService; - @Autowired - private ISysClient sysClient; - @Autowired - private IUserClient userClient; - @Autowired - private IMessageClient messageClient; - @Autowired - private PersonManagemetMapper personManagemetMapper; - @Autowired - private IMessageConfigClient messageConfigClient; - - /** - * realId刷新 - */ - @XxlJob(CERTIFICATET_DEAD_LINE_NOTICE) -// @Scheduled(cron = "0 */1 * * * ? ") - public ReturnT certificatetDeadLineNotice(String param) throws ParseException { - Date endTime = new Date(); - if (Func.isBlank(param)) { - endTime = new SimpleDateFormat("yyyy-MM-dd").parse(param); - } - CertificatetNoticeEntity noticeEntity = iImsCertificatetNoticeService.getOne(Wrappers.lambdaQuery() - .eq(CertificatetNoticeEntity::getIsDeleted, 0) - .last("limit 1;")); - //用户档案过期截止时间 - Date date = DateUtil.plusDays(endTime, noticeEntity.getSafeTime()); - List list = iImsCertificatetService.list(Wrappers.lambdaQuery() - .le(CertificatetEntity::getDeadTime, date)); - String noticeUsers = noticeEntity.getNoticeUsers(); - List userList = Arrays.asList(noticeUsers.split(",")); - if (CollectionUtil.isNotEmpty(userList) && CollectionUtil.isNotEmpty(list)) { - List personIds = list.stream().map(CertificatetEntity::getPersonId).collect(Collectors.toList()); - List personManagemetEntities = personManagemetMapper.selectList(Wrappers.query().lambda().in(PersonManagemetEntity::getId, personIds)); - String personNotice=""; - if (CollectionUtil.isNotEmpty(personManagemetEntities)) { - personNotice = personManagemetEntities.stream().map(PersonManagemetEntity::getName).collect(Collectors.joining(",")); - } - if ("1".equals(noticeEntity.getSendType())) { - sendSmsByUserList(userList, date,personNotice); - } - sendMessage(list.get(0), noticeEntity.getSafeTime(), noticeEntity.getNoticeUsers(),personNotice); - } - return new ReturnT<>("SUCCESS"); - } - - private void sendSmsByUserList(List userList, Date date,String personNotice) { - //区分用户 - for (String s : userList) { - User user = UserCache.getUser(Long.valueOf(s)); - String phone = ""; - if (ObjectUtil.isNotEmpty(user)) { - phone = user.getPhone(); - } - //短信推送 - String code = "certificatetNotice"; - SmsConfigEntity smsConfigEntity = messageConfigClient.getSmsConfigByBusinessKey(code); - Map contentParams = new HashMap<>(2); - contentParams.put("one", personNotice); - String deadLine = DateUtil.format(date, "yyyy-MM-dd"); - contentParams.put("two", deadLine); - smsConfigEntity.setTemplateParam(JSONObject.toJSONString(contentParams)); - smsConfigEntity.setPhones(phone); - messageConfigClient.pushSmsMessageByConfig(smsConfigEntity); - } - } - - private void sendMessage(CertificatetEntity certificatetEntity, Integer date, String users,String personNotice) { -// //注意:通知人是创建人所在机构 - BusinessMessageDTO message = new BusinessMessageDTO(); - message.setBusinessClassify("system"); - message.setBusinessKey(MessageConstants.BusinessClassifyEnum.CERTIFICATETNOTICE.getKey()); - message.setSubject(MessageConstants.BusinessClassifyEnum.CERTIFICATETNOTICE.getDescription()); - message.setTaskId(System.currentTimeMillis()); - message.setTenantId("200000"); - String countent = - personNotice + "的证书即将到期,请提交新的证书资料"; - message.setContent(countent); - message.setDeptId(certificatetEntity.getCreateDept()); - R deptName = sysClient.getDeptName(certificatetEntity.getCreateDept()); - if (deptName.isSuccess()) { - message.setDeptName(deptName.getData()); - } - message.setUserIds(users); - User admin = userClient.userByAccount("200000", "admin").getData(); - message.setCreateUser(admin.getId()); - messageClient.sendAppAndWsMsgByUsers(message); - } - - -} \ No newline at end of file diff --git a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/IImsPresonManagementService.java b/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/IImsPresonManagementService.java new file mode 100644 index 0000000..bc00a78 --- /dev/null +++ b/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/IImsPresonManagementService.java @@ -0,0 +1,21 @@ +package com.hnac.hzims.scheduled.service.basic; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; +import com.hnac.hzims.basic.entity.PersonManagemetEntity; +import com.hnac.hzims.basic.vo.PersonManagemetExportVo; +import com.hnac.hzims.basic.vo.PersonManagemetVo; +import org.springblade.core.mp.support.Query; +import org.springblade.core.tool.api.R; + +import java.util.List; + +/** + * 服务类 + * + * @author Chill + */ +public interface IImsPresonManagementService extends IService { + + +} diff --git a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/impl/CertificatetNoticeServiceImpl.java b/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/impl/CertificatetNoticeServiceImpl.java index b4e956d..f1b2210 100644 --- a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/impl/CertificatetNoticeServiceImpl.java +++ b/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/impl/CertificatetNoticeServiceImpl.java @@ -1,5 +1,6 @@ package com.hnac.hzims.scheduled.service.basic.impl; +import com.baomidou.dynamic.datasource.annotation.DS; import com.hnac.hzims.basic.entity.CertificatetNoticeEntity; import com.hnac.hzims.scheduled.mapper.basic.CertificatetNoticeMapper; import com.hnac.hzims.scheduled.service.basic.IImsCertificatetNoticeService; @@ -17,5 +18,6 @@ import org.springframework.stereotype.Service; @Service @Slf4j @RequiredArgsConstructor +@DS("basic") public class CertificatetNoticeServiceImpl extends BaseServiceImpl implements IImsCertificatetNoticeService { } diff --git a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/impl/CertificatetServiceImpl.java b/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/impl/CertificatetServiceImpl.java index 8849e80..79b890c 100644 --- a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/impl/CertificatetServiceImpl.java +++ b/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/impl/CertificatetServiceImpl.java @@ -1,5 +1,6 @@ package com.hnac.hzims.scheduled.service.basic.impl; +import com.baomidou.dynamic.datasource.annotation.DS; import com.hnac.hzims.basic.entity.CertificatetEntity; import com.hnac.hzims.scheduled.mapper.basic.CertificatetMapper; import com.hnac.hzims.scheduled.service.basic.IImsCertificatetService; @@ -17,5 +18,6 @@ import org.springframework.stereotype.Service; @Service @Slf4j @RequiredArgsConstructor +@DS("basic") public class CertificatetServiceImpl extends BaseServiceImpl implements IImsCertificatetService { } diff --git a/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/impl/PresonManagementServiceImpl.java b/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/impl/PresonManagementServiceImpl.java new file mode 100644 index 0000000..04b2f84 --- /dev/null +++ b/hzims-service/hzims-scheduled/src/main/java/com/hnac/hzims/scheduled/service/basic/impl/PresonManagementServiceImpl.java @@ -0,0 +1,27 @@ +package com.hnac.hzims.scheduled.service.basic.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.hnac.hzims.basic.entity.PersonManagemetEntity; +import com.hnac.hzims.scheduled.mapper.basic.PersonManagemetMapper; +import com.hnac.hzims.scheduled.service.basic.IImsPresonManagementService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springblade.core.mp.base.BaseServiceImpl; +import org.springframework.stereotype.Service; + + + +/** + * 人员信息实现类 + * + * @author ty + */ +@Service +@Slf4j +@RequiredArgsConstructor +@DS("basic") +public class PresonManagementServiceImpl extends BaseServiceImpl implements IImsPresonManagementService { + + + +} diff --git a/hzims-service/hzims-scheduled/src/main/resources/mapper/basic/CertificatetMapper.xml b/hzims-service/hzims-scheduled/src/main/resources/mapper/basic/CertificatetMapper.xml new file mode 100644 index 0000000..6941d55 --- /dev/null +++ b/hzims-service/hzims-scheduled/src/main/resources/mapper/basic/CertificatetMapper.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/hzims-service/hzims-scheduled/src/main/resources/mapper/basic/CertificatetNoticeMapper.xml b/hzims-service/hzims-scheduled/src/main/resources/mapper/basic/CertificatetNoticeMapper.xml new file mode 100644 index 0000000..c951079 --- /dev/null +++ b/hzims-service/hzims-scheduled/src/main/resources/mapper/basic/CertificatetNoticeMapper.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/hzims-service/hzims-scheduled/src/main/resources/mapper/basic/PersonManagemetMapper.xml b/hzims-service/hzims-scheduled/src/main/resources/mapper/basic/PersonManagemetMapper.xml new file mode 100644 index 0000000..409cbfb --- /dev/null +++ b/hzims-service/hzims-scheduled/src/main/resources/mapper/basic/PersonManagemetMapper.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +