Commit 0a87cf26 authored by huangcb's avatar huangcb

完善模型管理功能接口

parent f15db100
......@@ -18,6 +18,7 @@ public class ECode {
public static final ECode PARAM_ERROR = new ECode(600, "参数不合法");
public static final ECode TOKEN_INVALID = new ECode(601, "无效的Token");
public static final ECode TOKEN_EXPIRED = new ECode(602, "Token已过期");
public static final ECode BIZ_PARAM_ERROR = new ECode(1000, "业务参数错误");
public static final ECode BATCHID_FORMATTOR_ERROR = new ECode(11001, "时间格式错误");
public static final ECode BATCHID_LENTGH_ERROR = new ECode(11001, "长度错误");
......
......@@ -40,6 +40,17 @@ public class ReqUtils {
}
}
/**
* description 获取当前请求的数据权限
* param []
* return java.lang.String
* author Administrator
* createTime 2020/05/25 13:55
**/
public static String getRequestDataPerm() {
return getRequestHeader(GatewayHeaders.DATA_PERM);
}
/**
* description 获取当前请求的用户ID
* param []
......
......@@ -40,13 +40,13 @@ public class PageResultVO {
/**
* 数据
**/
private List<?> record;
private List<?> records;
public PageResultVO(IPage page, List<?> record) {
public PageResultVO(IPage page, List<?> records) {
this.pageSize = page.getSize();
this.pageNum = page.getCurrent();
this.total = page.getTotal();
this.recordSize = Long.parseLong(String.valueOf(page.getRecords().size()));
this.record = record;
this.records = records;
}
}
......@@ -3,14 +3,17 @@ package com.esv.datacenter.iot.module.omodel.controller;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.esv.datacenter.iot.common.exception.EException;
import com.esv.datacenter.iot.common.response.ECode;
import com.esv.datacenter.iot.common.response.EResponse;
import com.esv.datacenter.iot.common.util.ReqUtils;
import com.esv.datacenter.iot.common.validator.groups.ValidatorInsert;
import com.esv.datacenter.iot.common.validator.groups.ValidatorList;
import com.esv.datacenter.iot.common.validator.groups.*;
import com.esv.datacenter.iot.module.omodel.form.ModelPropertyForm;
import com.esv.datacenter.iot.module.omodel.form.ObjectModelForm;
import com.esv.datacenter.iot.module.omodel.service.ObjectModelInstanceService;
import com.esv.datacenter.iot.module.omodel.service.ObjectModelService;
import com.esv.gateway.common.DataPermsType;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
......@@ -18,6 +21,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Objects;
/**
* @description: 物模型Controller
......@@ -32,9 +36,11 @@ import java.util.List;
public class ObjectModelController {
private ObjectModelService objectModelService;
private ObjectModelInstanceService objectModelInstanceService;
public ObjectModelController(ObjectModelService objectModelService) {
public ObjectModelController(ObjectModelService objectModelService, ObjectModelInstanceService objectModelInstanceService) {
this.objectModelService = objectModelService;
this.objectModelInstanceService = objectModelInstanceService;
}
/**
......@@ -69,6 +75,98 @@ public class ObjectModelController {
**/
@PostMapping("/list")
public EResponse list(@RequestBody @Validated(ValidatorList.class) ObjectModelForm form) throws EException {
if (!DataPermsType.DATA_PERM_ALL.equals(ReqUtils.getRequestDataPerm())) {
form.setTenantId(ReqUtils.getRequestTenantId());
}
if (Objects.nonNull(StringUtils.trimToNull(form.getName()))) {
form.setName("%" + form.getName() + "%");
}
return EResponse.ok(objectModelService.getModel4Page(form));
}
/**
* @description 获取模型详情
* @param form:
* @return com.esv.datacenter.iot.common.response.EResponse
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 10:40
**/
@PostMapping("/detail")
public EResponse detail(@RequestBody @Validated(ValidatorDetail.class) ObjectModelForm form) throws EException {
// 校验模型ID是否有效
this.checkIsValidModelId(form.getId());
return EResponse.ok(objectModelService.getModelDetail(form));
}
/**
* @description 编辑模型
* @param form:
* @return com.esv.datacenter.iot.common.response.EResponse
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 10:40
**/
@PostMapping("/edit")
public EResponse edit(@RequestBody @Validated(ValidatorUpdate.class) ObjectModelForm form) throws EException {
// 校验模型ID是否有效
this.checkIsValidModelId(form.getId());
return EResponse.ok(objectModelService.updateModel(form));
}
/**
* @description 删除模型
* @param form:
* @return com.esv.datacenter.iot.common.response.EResponse
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 11:35
**/
@PostMapping("/delete")
public EResponse delete(@RequestBody @Validated(ValidatorDelete.class) ObjectModelForm form) throws EException {
// 校验模型ID是否有效
this.checkIsValidModelId(form.getId());
objectModelService.deleteModel(form.getId());
return EResponse.ok();
}
/**
* @description 获取所有模型列表
* @return com.esv.datacenter.iot.common.response.EResponse
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 13:10
**/
@PostMapping("/all")
public EResponse all() throws EException {
return EResponse.ok(objectModelService.getAllModeList());
}
/**
* @description 获取指定模型的实例列表
* @param form:
* @return com.esv.datacenter.iot.common.response.EResponse
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 13:43
**/
@PostMapping("/getModelInstanceList")
public EResponse getModelInstanceList(@RequestBody @Validated(ValidatorDetail.class) ObjectModelForm form) throws EException {
// 校验模型ID是否有效
this.checkIsValidModelId(form.getId());
return EResponse.ok(objectModelInstanceService.getModelInstanceList(form.getId()));
}
/**
* @description 校验模型ID是否有效
* @param modelId:
* @return void
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 14:25
**/
private void checkIsValidModelId(Long modelId) {
if (!objectModelService.isModelExits(modelId)) {
throw new EException(ECode.BIZ_PARAM_ERROR.code(), "无效的模型id值");
}
}
}
......@@ -26,4 +26,13 @@ public interface ObjectModelDao extends BaseMapper<ObjectModelEntity> {
**/
IPage select4Page(IPage page, ObjectModelForm queryObj);
/**
* @description 逻辑删除指定模型
* @param entity:
* @return java.lang.Integer
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 14:06
**/
Integer logicDeleteModel(ObjectModelEntity entity);
}
......@@ -14,4 +14,13 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ObjectModelPropertyDao extends BaseMapper<ObjectModelPropertyEntity> {
/**
* @description 逻辑删除指定模型的所有属性
* @param entity:
* @return java.lang.Integer
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 13:28
**/
Integer logicDeleteModelProperty(ObjectModelPropertyEntity entity);
}
package com.esv.datacenter.iot.module.omodel.entity;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.io.Serializable;
import java.util.Date;
import lombok.Data;
/**
* 物模型属性表
......@@ -21,7 +26,6 @@ public class ObjectModelPropertyEntity implements Serializable {
/**
*
*/
@TableId
private Long id;
/**
* 租户ID
......@@ -69,12 +73,10 @@ public class ObjectModelPropertyEntity implements Serializable {
/**
* 创建者
*/
@TableField(fill = FieldFill.INSERT)
private String createUser;
/**
* 修改者
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateUser;
/**
* 创建时间
......@@ -85,4 +87,9 @@ public class ObjectModelPropertyEntity implements Serializable {
*/
private Date updateTime;
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
}
}
package com.esv.datacenter.iot.module.omodel.form;
import com.esv.datacenter.iot.common.validator.groups.ValidatorInsert;
import com.esv.datacenter.iot.common.validator.groups.ValidatorList;
import com.esv.datacenter.iot.common.validator.groups.*;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
......@@ -24,18 +23,27 @@ public class ObjectModelForm {
/**
*
*/
@NotNull(message = "[模型ID]不能为空", groups = {ValidatorDetail.class, ValidatorUpdate.class, ValidatorDelete.class})
private Long id;
/**
* 租户ID
*/
private Long tenantId;
/**
* 部门ID
*/
private Long departmentId;
/**
* 模型名称
*/
@Length(max = 50, message = "[模型名称]长度不合法", groups = {ValidatorInsert.class, ValidatorList.class})
@NotBlank(message = "[模型名称]不能为空", groups = {ValidatorInsert.class})
@Length(max = 50, message = "[模型名称]长度不合法", groups = {ValidatorInsert.class, ValidatorList.class, ValidatorUpdate.class})
@NotBlank(message = "[模型名称]不能为空", groups = {ValidatorInsert.class, ValidatorUpdate.class})
private String name;
/**
* 模型描述
*/
@Length(max = 200, message = "[模型描述]长度不合法", groups = {ValidatorInsert.class})
@NotBlank(message = "[模型描述]不能为空", groups = {ValidatorInsert.class})
@Length(max = 200, message = "[模型描述]长度不合法", groups = {ValidatorInsert.class, ValidatorUpdate.class})
@NotBlank(message = "[模型描述]不能为空", groups = {ValidatorInsert.class, ValidatorUpdate.class})
private String description;
/**
......
......@@ -2,6 +2,9 @@ package com.esv.datacenter.iot.module.omodel.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.esv.datacenter.iot.module.omodel.entity.ObjectModelInstanceEntity;
import com.esv.datacenter.iot.module.omodel.vo.ModelInstanceVO;
import java.util.List;
/**
* 物模型实例表
......@@ -12,5 +15,14 @@ import com.esv.datacenter.iot.module.omodel.entity.ObjectModelInstanceEntity;
*/
public interface ObjectModelInstanceService extends IService<ObjectModelInstanceEntity> {
/**
* @description 获取指定模型的实例列表
* @param modelId:
* @return java.util.List<com.esv.datacenter.iot.module.omodel.vo.ModelInstanceVO>
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 13:37
**/
List<ModelInstanceVO> getModelInstanceList(Long modelId);
}
......@@ -2,6 +2,10 @@ package com.esv.datacenter.iot.module.omodel.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.esv.datacenter.iot.module.omodel.entity.ObjectModelPropertyEntity;
import com.esv.datacenter.iot.module.omodel.form.ModelPropertyForm;
import com.esv.datacenter.iot.module.omodel.vo.ModelPropertyVO;
import java.util.List;
/**
* 物模型属性表
......@@ -12,5 +16,33 @@ import com.esv.datacenter.iot.module.omodel.entity.ObjectModelPropertyEntity;
*/
public interface ObjectModelPropertyService extends IService<ObjectModelPropertyEntity> {
/**
* @description 逻辑删除指定模型的所有属性
* @param entity:
* @return java.lang.Integer
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 13:28
**/
Integer logicDeleteModelProperty(ObjectModelPropertyEntity entity);
/**
* @description 获取指定模型的属性列表
* @param modelId:
* @return java.util.List<com.esv.datacenter.iot.module.omodel.vo.ModelPropertyVO>
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 14:32
**/
List<ModelPropertyVO> getModelPropertyList(Long modelId);
/**
* @description 保存模型属性
* @param modelId:
* @param propertyList:
* @return void
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 14:42
**/
void saveModelProperty(Long modelId, List<ModelPropertyForm> propertyList);
}
......@@ -4,6 +4,10 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.esv.datacenter.iot.common.vo.PageResultVO;
import com.esv.datacenter.iot.module.omodel.entity.ObjectModelEntity;
import com.esv.datacenter.iot.module.omodel.form.ObjectModelForm;
import com.esv.datacenter.iot.module.omodel.vo.ModelDetailVO;
import com.esv.datacenter.iot.module.omodel.vo.ModelVO;
import java.util.List;
/**
* 物模型表
......@@ -32,5 +36,58 @@ public interface ObjectModelService extends IService<ObjectModelEntity> {
**/
PageResultVO getModel4Page(ObjectModelForm queryObj);
/**
* @description 获取模型详情
* @param form:
* @return com.esv.datacenter.iot.module.omodel.vo.ModelDetailVO
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 10:25
**/
ModelDetailVO getModelDetail(ObjectModelForm form);
/**
* @description 更新模型
* @param form:
* @return java.lang.Integer
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 10:48
**/
Integer updateModel(ObjectModelForm form);
/**
* @description 模型实例数
* @param modelId:
* @return java.lang.Integer
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 11:29
**/
Integer modelInstanceCount(Long modelId);
/**
* @description 删除模型
* @param modelId:
* @return void
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 11:33
**/
void deleteModel(Long modelId);
/**
* @description 获取所有模型列表
* @return java.util.List<com.esv.datacenter.iot.module.omodel.vo.ModelVO>
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 13:04
**/
List<ModelVO> getAllModeList();
/**
* @description 判断模型是否存在
* @param modelId:
* @return java.lang.Boolean
* @author huangChaobin@esvtek.com
* @createTime 2020/08/01 14:19
**/
Boolean isModelExits(Long modelId);
}
package com.esv.datacenter.iot.module.omodel.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.esv.datacenter.iot.common.em.DbDeletedEnum;
import com.esv.datacenter.iot.module.omodel.dao.ObjectModelInstanceDao;
import com.esv.datacenter.iot.module.omodel.entity.ObjectModelInstanceEntity;
import com.esv.datacenter.iot.module.omodel.service.ObjectModelInstanceService;
import com.esv.datacenter.iot.module.omodel.vo.ModelInstanceVO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
@Service("objectModelInstanceService")
public class ObjectModelInstanceServiceImpl extends ServiceImpl<ObjectModelInstanceDao, ObjectModelInstanceEntity> implements ObjectModelInstanceService {
@Override
public List<ModelInstanceVO> getModelInstanceList(Long modelId) {
List<ObjectModelInstanceEntity> entityList = this.getBaseMapper().selectList(new LambdaQueryWrapper<ObjectModelInstanceEntity>()
.eq(ObjectModelInstanceEntity::getDeleted, DbDeletedEnum.NO.getCode())
.eq(ObjectModelInstanceEntity::getModelId, modelId)
.orderByAsc(ObjectModelInstanceEntity::getInstanceName));
List<ModelInstanceVO> voList = new ArrayList<>();
for (ObjectModelInstanceEntity entity : entityList) {
ModelInstanceVO vo = new ModelInstanceVO();
BeanUtils.copyProperties(entity, vo);
vo.setCreateTime(entity.getCreateTime().getTime());
vo.setUpdateTime(entity.getUpdateTime().getTime());
voList.add(vo);
}
return voList;
}
}
\ No newline at end of file
package com.esv.datacenter.iot.module.omodel.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.esv.datacenter.iot.common.em.DbDeletedEnum;
import com.esv.datacenter.iot.module.omodel.dao.ObjectModelPropertyDao;
import com.esv.datacenter.iot.module.omodel.entity.ObjectModelPropertyEntity;
import com.esv.datacenter.iot.module.omodel.form.ModelPropertyForm;
import com.esv.datacenter.iot.module.omodel.service.ObjectModelPropertyService;
import com.esv.datacenter.iot.module.omodel.vo.ModelPropertyVO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.List;
@Service("objectModelPropertyService")
public class ObjectModelPropertyServiceImpl extends ServiceImpl<ObjectModelPropertyDao, ObjectModelPropertyEntity> implements ObjectModelPropertyService {
@Override
public Integer logicDeleteModelProperty(ObjectModelPropertyEntity entity) {
return this.getBaseMapper().logicDeleteModelProperty(entity);
}
@Override
public List<ModelPropertyVO> getModelPropertyList(Long modelId) {
List<ObjectModelPropertyEntity> entityList = this.getBaseMapper()
.selectList(new LambdaQueryWrapper<ObjectModelPropertyEntity>()
.eq(ObjectModelPropertyEntity::getModelId, modelId)
.eq(ObjectModelPropertyEntity::getDeleted, DbDeletedEnum.NO.getCode())
.orderByAsc(ObjectModelPropertyEntity::getSortNum));
List<ModelPropertyVO> voList = new ArrayList<>();
for (ObjectModelPropertyEntity entity : entityList) {
ModelPropertyVO vo = new ModelPropertyVO();
BeanUtils.copyProperties(entity, vo);
vo.setCreateTime(entity.getCreateTime().getTime());
vo.setUpdateTime(entity.getUpdateTime().getTime());
voList.add(vo);
}
return voList;
}
@Override
@Transactional(rollbackFor = Exception.class)
public void saveModelProperty(Long modelId, List<ModelPropertyForm> propertyList) {
// 删除模型属性
ObjectModelPropertyEntity propertyEntity = new ObjectModelPropertyEntity();
propertyEntity.setDeleted(DbDeletedEnum.YES.getCode());
propertyEntity.setModelId(modelId);
this.logicDeleteModelProperty(propertyEntity);
// 新增模型属性
List<ObjectModelPropertyEntity> modelPropertyEntityList = new ArrayList<>();
for (ModelPropertyForm propertyForm : propertyList) {
ObjectModelPropertyEntity entity = new ObjectModelPropertyEntity();
BeanUtils.copyProperties(propertyForm, entity);
entity.setModelId(modelId);
modelPropertyEntityList.add(entity);
}
this.saveBatch(modelPropertyEntityList);
// 更新属性排序值
for (ObjectModelPropertyEntity modelPropertyEntity : modelPropertyEntityList) {
ObjectModelPropertyEntity entity = new ObjectModelPropertyEntity();
entity.setId(modelPropertyEntity.getId());
entity.setSortNum(modelPropertyEntity.getId());
this.updateById(entity);
}
}
}
\ No newline at end of file
package com.esv.datacenter.iot.module.omodel.vo;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import java.util.List;
/**
* @description:
* @author: huangchaobin@esvtek.com
* @createTime: 2020/08/01 10:22
* @version:1.0
*/
@Data
public class ModelDetailVO extends ModelVO {
/**
* 模型是否有实例
*/
Boolean hasInstance;
/**
* 模型实例数
*/
Integer instanceCount;
/**
* 模型属性
*/
List<ModelPropertyVO> propertyList;
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
}
}
package com.esv.datacenter.iot.module.omodel.vo;
import lombok.Data;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
/**
* @description:
* @author: huangchaobin@esvtek.com
* @createTime: 2020/08/01 13:35
* @version:1.0
*/
@Data
public class ModelInstanceVO {
/**
*
*/
private Long id;
/**
* 模型ID
*/
private Long modelId;
/**
* 实例名称
*/
private String instanceName;
/**
* 实例描述
*/
private String description;
/**
* 创建者
*/
private String createUser;
/**
* 修改者
*/
private String updateUser;
/**
* 创建时间
*/
private Long createTime;
/**
* 修改时间
*/
private Long updateTime;
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
}
}
package com.esv.datacenter.iot.module.omodel.vo;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.Data;
/**
* @description:
* @author: huangchaobin@esvtek.com
* @createTime: 2020/08/01 10:20
* @version:1.0
*/
@Data
public class ModelPropertyVO {
/**
*
*/
@TableId
private Long id;
/**
* 租户ID
*/
private Long tenantId;
/**
* 部门ID
*/
private Long departmentId;
/**
* 模型ID
*/
private Long modelId;
/**
* 属性代码
*/
private String propertyCode;
/**
* 属性名称
*/
private String propertyName;
/**
* 属性类型(字典表)
*/
private Integer propertyType;
/**
* 属性默认值
*/
private String propertyDefaultValue;
/**
* 属性单位
*/
private String propertyUnit;
/**
* 排列序号
*/
private Long sortNum;
/**
* 是否删除:0-未删除、1-已删除
*/
@TableLogic
private Boolean deleted;
/**
* 创建者
*/
@TableField(fill = FieldFill.INSERT)
private String createUser;
/**
* 修改者
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private String updateUser;
/**
* 创建时间
*/
private Long createTime;
/**
* 修改时间
*/
private Long updateTime;
}
......@@ -11,7 +11,7 @@ import org.apache.commons.lang3.builder.ToStringStyle;
* @version:1.0
*/
@Data
public class ObjectModelVO {
public class ModelVO {
/**
*
......
......@@ -22,11 +22,20 @@
resultType="com.esv.datacenter.iot.module.omodel.entity.ObjectModelEntity">
select *
from base_object_model
where 1=1
where deleted = false
<if test="queryObj.tenantId != null">
and tenant_id = #{queryObj.tenantId}
</if>
<if test="queryObj.name != null">
and name = #{queryObj.name}
and name like #{queryObj.name}
</if>
ORDER BY name ASC
</select>
<update id="logicDeleteModel" parameterType="com.esv.datacenter.iot.module.omodel.entity.ObjectModelEntity">
update base_object_model
set deleted = #{deleted}
where id = #{id}
</update>
</mapper>
\ No newline at end of file
......@@ -22,5 +22,10 @@
<result property="updateTime" column="update_time"/>
</resultMap>
<update id="logicDeleteModelProperty" parameterType="com.esv.datacenter.iot.module.omodel.entity.ObjectModelPropertyEntity">
update base_object_model_property
set deleted = #{deleted}
where model_id = #{modelId}
</update>
</mapper>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment