commit
1a25e693b9
|
|
@ -24,6 +24,8 @@ public interface DataReferenceManager {
|
|||
String TYPE_NETWORK = "network";
|
||||
//数据类型:关系配置
|
||||
String TYPE_RELATION = "relation";
|
||||
//数据类型:消息协议
|
||||
String TYPE_PROTOCOL = "protocol";
|
||||
|
||||
/**
|
||||
* 判断指定数据类型的数据是否已经被其他地方所引用
|
||||
|
|
|
|||
|
|
@ -0,0 +1,122 @@
|
|||
package org.jetlinks.community.auth.initialize;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
|
||||
import org.hswebframework.web.authorization.DefaultDimensionType;
|
||||
import org.hswebframework.web.authorization.Permission;
|
||||
import org.hswebframework.web.authorization.events.AuthorizationInitializeEvent;
|
||||
import org.hswebframework.web.authorization.simple.SimpleAuthentication;
|
||||
import org.hswebframework.web.authorization.simple.SimplePermission;
|
||||
import org.hswebframework.web.system.authorization.api.entity.ActionEntity;
|
||||
import org.hswebframework.web.system.authorization.api.entity.PermissionEntity;
|
||||
import org.hswebframework.web.system.authorization.defaults.service.DefaultPermissionService;
|
||||
import org.jetlinks.community.auth.entity.MenuEntity;
|
||||
import org.jetlinks.community.auth.entity.MenuView;
|
||||
import org.jetlinks.community.auth.service.DefaultMenuService;
|
||||
import org.jetlinks.community.auth.service.request.MenuGrantRequest;
|
||||
import org.jetlinks.community.auth.web.request.AuthorizationSettingDetail;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Component
|
||||
public class MenuAuthenticationInitializeService {
|
||||
|
||||
private final DefaultMenuService menuService;
|
||||
|
||||
private final DefaultPermissionService permissionService;
|
||||
|
||||
/**
|
||||
* 根据角色配置的菜单权限来重构权限信息
|
||||
*
|
||||
* @param event 权限初始化事件
|
||||
*/
|
||||
@EventListener
|
||||
public void refactorPermission(AuthorizationInitializeEvent event) {
|
||||
if (event.getAuthentication().getDimensions().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
event.async(
|
||||
Mono
|
||||
.zip(
|
||||
// T1: 权限定义列表
|
||||
permissionService
|
||||
.createQuery()
|
||||
.where(PermissionEntity::getStatus, 1)
|
||||
.fetch()
|
||||
.collectMap(PermissionEntity::getId, Function.identity()),
|
||||
// T2: 菜单定义列表
|
||||
menuService
|
||||
.createQuery()
|
||||
.where(MenuEntity::getStatus, 1)
|
||||
.fetch()
|
||||
.collectList(),
|
||||
// T3: 角色赋予的菜单列表
|
||||
menuService
|
||||
.getGrantedMenus(QueryParamEntity.of(), event
|
||||
.getAuthentication()
|
||||
.getDimensions())
|
||||
.collectList()
|
||||
.filter(CollectionUtils::isNotEmpty)
|
||||
)
|
||||
.<Permission>flatMapIterable(tp3 -> {
|
||||
Map<String, PermissionEntity> permissions = tp3.getT1();
|
||||
List<MenuEntity> menus = tp3.getT2();
|
||||
List<MenuView> grantedMenus = tp3.getT3();
|
||||
MenuGrantRequest request = new MenuGrantRequest();
|
||||
request.setTargetType(DefaultDimensionType.role.getId());
|
||||
request.setTargetId("merge");
|
||||
request.setMenus(grantedMenus);
|
||||
AuthorizationSettingDetail detail = request.toAuthorizationSettingDetail(menus);
|
||||
return detail
|
||||
.getPermissionList()
|
||||
.stream()
|
||||
.map(per -> {
|
||||
PermissionEntity entity = permissions.get(per.getId());
|
||||
if (entity == null || per.getActions() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Set<String> actions;
|
||||
if (CollectionUtils.isEmpty(entity.getActions())) {
|
||||
actions = new HashSet<>();
|
||||
} else {
|
||||
Set<String> defActions = entity
|
||||
.getActions()
|
||||
.stream()
|
||||
.map(ActionEntity::getAction)
|
||||
.collect(Collectors.toSet());
|
||||
actions = new HashSet<>(per.getActions());
|
||||
actions.retainAll(defActions);
|
||||
}
|
||||
|
||||
return SimplePermission
|
||||
.builder()
|
||||
.id(entity.getId())
|
||||
.name(entity.getName())
|
||||
.options(entity.getProperties())
|
||||
.actions(actions)
|
||||
.build();
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toList());
|
||||
})
|
||||
.collectList()
|
||||
.filter(CollectionUtils::isNotEmpty)
|
||||
.doOnNext(mapping -> {
|
||||
SimpleAuthentication authentication = new SimpleAuthentication();
|
||||
authentication.setUser(event.getAuthentication().getUser());
|
||||
authentication.setPermissions(mapping);
|
||||
event.setAuthentication(event.getAuthentication().merge(authentication));
|
||||
})
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
package org.jetlinks.community.device.entity;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.hswebframework.web.api.crud.entity.GenericTreeSortSupportEntity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
public class DeviceCategory extends GenericTreeSortSupportEntity<String> {
|
||||
|
||||
@Schema(description = "ID")
|
||||
private String id;
|
||||
|
||||
@Schema(description = "标识")
|
||||
private String key;
|
||||
|
||||
@Schema(description = "名称")
|
||||
private String name;
|
||||
|
||||
@Schema(description = "父节点标识")
|
||||
private String parentId;
|
||||
|
||||
@Schema(description = "子节点")
|
||||
private List<DeviceCategory> children;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
package org.jetlinks.community.device.entity;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.hswebframework.ezorm.rdb.mapping.annotation.ColumnType;
|
||||
import org.hswebframework.ezorm.rdb.mapping.annotation.Comment;
|
||||
import org.hswebframework.ezorm.rdb.mapping.annotation.DefaultValue;
|
||||
import org.hswebframework.web.api.crud.entity.GenericTreeSortSupportEntity;
|
||||
import org.hswebframework.web.api.crud.entity.RecordCreationEntity;
|
||||
import org.hswebframework.web.crud.annotation.EnableEntityEvent;
|
||||
import org.hswebframework.web.crud.generator.Generators;
|
||||
import org.hswebframework.web.validator.CreateGroup;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import java.sql.JDBCType;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Table(name = "dev_product_category")
|
||||
@Comment("产品分类信息表")
|
||||
@EnableEntityEvent
|
||||
public class DeviceCategoryEntity extends GenericTreeSortSupportEntity<String> implements RecordCreationEntity {
|
||||
|
||||
@Override
|
||||
@Id
|
||||
@Column(length = 64, updatable = false)
|
||||
@GeneratedValue(generator = Generators.SNOW_FLAKE)
|
||||
@NotBlank(message = "ID不能为空", groups = CreateGroup.class)
|
||||
@Pattern(regexp = "^[0-9a-zA-Z_\\-|]+$", message = "ID只能由数字,字母,下划线和中划线组成", groups = CreateGroup.class)
|
||||
public String getId() {
|
||||
return super.getId();
|
||||
}
|
||||
|
||||
@Schema(description = "标识")
|
||||
@Column(nullable = false,length = 64)
|
||||
@NotBlank(message = "标识不能为空", groups = CreateGroup.class)
|
||||
@GeneratedValue(generator = Generators.SNOW_FLAKE)
|
||||
@Pattern(regexp = "^[0-9a-zA-Z_\\-]+$", message = "分类标识只能由数字,字母,下划线和中划线组成")
|
||||
private String key;
|
||||
|
||||
@Schema(description = "名称")
|
||||
@Column(nullable = false)
|
||||
@NotBlank
|
||||
private String name;
|
||||
|
||||
@Schema(description = "说明")
|
||||
@Column
|
||||
private String description;
|
||||
|
||||
@Schema(description = "子节点")
|
||||
private List<DeviceCategoryEntity> children;
|
||||
|
||||
@Schema(description = "物模型")
|
||||
@Column
|
||||
@ColumnType(javaType = String.class, jdbcType = JDBCType.CLOB)
|
||||
private String metadata;
|
||||
|
||||
@Column(updatable = false)
|
||||
@Schema(
|
||||
description = "创建者ID(只读)"
|
||||
, accessMode = Schema.AccessMode.READ_ONLY
|
||||
)
|
||||
private String creatorId;
|
||||
|
||||
@Column(updatable = false)
|
||||
@DefaultValue(generator = Generators.CURRENT_TIME)
|
||||
@Schema(
|
||||
description = "创建时间(只读)"
|
||||
, accessMode = Schema.AccessMode.READ_ONLY
|
||||
)
|
||||
private Long createTime;
|
||||
}
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
package org.jetlinks.community.device.service;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import org.hswebframework.web.api.crud.entity.TreeSupportEntity;
|
||||
import org.hswebframework.web.crud.service.GenericReactiveTreeSupportCrudService;
|
||||
import org.hswebframework.web.id.IDGenerator;
|
||||
import org.jetlinks.community.device.entity.DeviceCategoryEntity;
|
||||
import org.springframework.boot.CommandLineRunner;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
@Service
|
||||
public class DeviceCategoryService extends GenericReactiveTreeSupportCrudService<DeviceCategoryEntity, String> implements CommandLineRunner {
|
||||
|
||||
@Override
|
||||
public IDGenerator<String> getIDGenerator() {
|
||||
return IDGenerator.MD5;
|
||||
}
|
||||
|
||||
private static final String category_splitter = "-";
|
||||
@Override
|
||||
public void setChildren(DeviceCategoryEntity entity, List<DeviceCategoryEntity> children) {
|
||||
entity.setChildren(children);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(String... args) {
|
||||
this
|
||||
.createQuery()
|
||||
.fetchOne()
|
||||
.switchIfEmpty(initDefaultData().then(Mono.empty()))
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
|
||||
static void rebuild(String parentId, List<DeviceCategoryEntity> children) {
|
||||
if (children == null) {
|
||||
return;
|
||||
}
|
||||
for (DeviceCategoryEntity child : children) {
|
||||
String id = child.getId();
|
||||
child.setId(parentId + category_splitter + id +category_splitter);
|
||||
child.setParentId(parentId +category_splitter);
|
||||
rebuild(parentId + category_splitter + id, child.getChildren());
|
||||
}
|
||||
}
|
||||
|
||||
private Mono<Void> initDefaultData() {
|
||||
return Mono
|
||||
.fromCallable(() -> {
|
||||
ClassPathResource resource = new ClassPathResource("device-category.json");
|
||||
|
||||
try (InputStream stream = resource.getInputStream()) {
|
||||
String json = StreamUtils.copyToString(stream, StandardCharsets.UTF_8);
|
||||
|
||||
List<DeviceCategoryEntity> all = JSON.parseArray(json, DeviceCategoryEntity.class);
|
||||
|
||||
List<DeviceCategoryEntity> root = TreeSupportEntity.list2tree(all, DeviceCategoryEntity::setChildren);
|
||||
|
||||
for (DeviceCategoryEntity category : root) {
|
||||
String id = category.getId();
|
||||
category.setId(category_splitter + id + category_splitter);
|
||||
category.setParentId(category_splitter + category.getParentId() + category_splitter);
|
||||
rebuild(category_splitter + id, category.getChildren());
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
})
|
||||
.flatMap(all -> save(Flux.fromIterable(all)))
|
||||
.then();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,48 +1,55 @@
|
|||
package org.jetlinks.community.device.service;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.hswebframework.web.crud.service.GenericReactiveCrudService;
|
||||
import org.hswebframework.web.exception.BusinessException;
|
||||
import org.hswebframework.web.exception.NotFoundException;
|
||||
import org.jetlinks.community.device.entity.ProtocolSupportEntity;
|
||||
import org.jetlinks.supports.protocol.management.ProtocolSupportLoader;
|
||||
import org.jetlinks.community.reference.DataReferenceManager;
|
||||
import org.jetlinks.supports.protocol.management.ProtocolSupportManager;
|
||||
import org.reactivestreams.Publisher;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@Service
|
||||
@Slf4j
|
||||
public class LocalProtocolSupportService extends GenericReactiveCrudService<ProtocolSupportEntity, String> {
|
||||
|
||||
@Autowired
|
||||
private ProtocolSupportManager supportManager;
|
||||
|
||||
@Autowired
|
||||
private ProtocolSupportLoader loader;
|
||||
private DataReferenceManager referenceManager;
|
||||
|
||||
@Override
|
||||
public Mono<Integer> deleteById(Publisher<String> idPublisher) {
|
||||
return Flux.from(idPublisher)
|
||||
.flatMap(id -> supportManager.remove(id).thenReturn(id))
|
||||
.as(super::deleteById);
|
||||
}
|
||||
|
||||
public Mono<Boolean> deploy(String id) {
|
||||
return findById(Mono.just(id))
|
||||
.switchIfEmpty(Mono.error(NotFoundException::new))
|
||||
.map(ProtocolSupportEntity::toDeployDefinition)
|
||||
.flatMap(def->loader.load(def).thenReturn(def))
|
||||
.onErrorMap(err->new BusinessException("无法加载协议:"+err.getMessage(),err))
|
||||
.flatMap(supportManager::save)
|
||||
.flatMap(r -> createUpdate()
|
||||
.set(ProtocolSupportEntity::getState, 1)
|
||||
.where(ProtocolSupportEntity::getId, id)
|
||||
.execute())
|
||||
.map(i -> i > 0);
|
||||
.switchIfEmpty(Mono.error(NotFoundException::new))
|
||||
.flatMap(r -> createUpdate()
|
||||
.set(ProtocolSupportEntity::getState, 1)
|
||||
.where(ProtocolSupportEntity::getId, id)
|
||||
.execute())
|
||||
.map(i -> i > 0);
|
||||
}
|
||||
|
||||
public Mono<Boolean> unDeploy(String id) {
|
||||
return findById(Mono.just(id))
|
||||
.switchIfEmpty(Mono.error(NotFoundException::new))
|
||||
.map(ProtocolSupportEntity::toUnDeployDefinition)
|
||||
.flatMap(supportManager::save)
|
||||
.flatMap(r -> createUpdate()
|
||||
.set(ProtocolSupportEntity::getState, 0)
|
||||
.where(ProtocolSupportEntity::getId, id)
|
||||
.execute())
|
||||
.map(i -> i > 0);
|
||||
// 消息协议被使用时,不能禁用
|
||||
return referenceManager
|
||||
.assertNotReferenced(DataReferenceManager.TYPE_PROTOCOL, id)
|
||||
.then(findById(Mono.just(id)))
|
||||
.switchIfEmpty(Mono.error(NotFoundException::new))
|
||||
.flatMap(r -> createUpdate()
|
||||
.set(ProtocolSupportEntity::getState, 0)
|
||||
.where(ProtocolSupportEntity::getId, id)
|
||||
.execute())
|
||||
.map(i -> i > 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
package org.jetlinks.community.device.service;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.hswebframework.web.crud.events.EntityBeforeDeleteEvent;
|
||||
import org.hswebframework.web.crud.events.EntityCreatedEvent;
|
||||
import org.hswebframework.web.crud.events.EntityModifyEvent;
|
||||
import org.hswebframework.web.crud.events.EntitySavedEvent;
|
||||
import org.hswebframework.web.exception.BusinessException;
|
||||
import org.jetlinks.community.device.entity.ProtocolSupportEntity;
|
||||
import org.jetlinks.community.reference.DataReferenceManager;
|
||||
import org.jetlinks.core.ProtocolSupport;
|
||||
import org.jetlinks.supports.protocol.management.ProtocolSupportLoader;
|
||||
import org.jetlinks.supports.protocol.management.ProtocolSupportManager;
|
||||
import org.springframework.context.event.EventListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* 协议事件处理类.
|
||||
*
|
||||
* @author zhangji 2022/4/1
|
||||
*/
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
public class ProtocolSupportHandler {
|
||||
private final DataReferenceManager referenceManager;
|
||||
private ProtocolSupportLoader loader;
|
||||
private ProtocolSupportManager supportManager;
|
||||
|
||||
//禁止删除已有网关使用的协议
|
||||
@EventListener
|
||||
public void handleProtocolDelete(EntityBeforeDeleteEvent<ProtocolSupportEntity> event) {
|
||||
event.async(
|
||||
Flux.fromIterable(event.getEntity())
|
||||
.flatMap(protocol -> referenceManager
|
||||
.assertNotReferenced(DataReferenceManager.TYPE_PROTOCOL, protocol.getId()))
|
||||
);
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void handleCreated(EntityCreatedEvent<ProtocolSupportEntity> event) {
|
||||
event.async(reloadProtocol(event.getEntity()));
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void handleSaved(EntitySavedEvent<ProtocolSupportEntity> event) {
|
||||
event.async(reloadProtocol(event.getEntity()));
|
||||
}
|
||||
|
||||
@EventListener
|
||||
public void handleModify(EntityModifyEvent<ProtocolSupportEntity> event) {
|
||||
event.async(reloadProtocol(event.getAfter()));
|
||||
}
|
||||
|
||||
// 重新加载协议
|
||||
private Mono<Void> reloadProtocol(Collection<ProtocolSupportEntity> protocol) {
|
||||
return Flux
|
||||
.fromIterable(protocol)
|
||||
.filter(entity -> entity.getState() != null)
|
||||
.map(entity -> entity.getState() == 1 ? entity.toDeployDefinition() : entity.toUnDeployDefinition())
|
||||
.flatMap(def -> loader
|
||||
//加载一下检验是否正确,然后就卸载
|
||||
.load(def)
|
||||
.doOnNext(ProtocolSupport::dispose)
|
||||
.thenReturn(def))
|
||||
.onErrorMap(err -> new BusinessException("error.unable_to_load_protocol", 500, err.getMessage()))
|
||||
.flatMap(supportManager::save)
|
||||
.then();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,85 +1,72 @@
|
|||
package org.jetlinks.community.device.web;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.hswebframework.web.api.crud.entity.TreeSupportEntity;
|
||||
import org.jetlinks.community.device.entity.DeviceCategory;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import reactor.core.publisher.Flux;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.hswebframework.web.api.crud.entity.QueryNoPagingOperation;
|
||||
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
|
||||
import org.hswebframework.web.api.crud.entity.TreeSupportEntity;
|
||||
import org.hswebframework.web.authorization.annotation.Authorize;
|
||||
import org.hswebframework.web.authorization.annotation.Resource;
|
||||
import org.hswebframework.web.crud.service.ReactiveCrudService;
|
||||
import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController;
|
||||
import org.jetlinks.community.device.entity.DeviceCategoryEntity;
|
||||
import org.jetlinks.community.device.service.DeviceCategoryService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/device/category")
|
||||
@Slf4j
|
||||
@Tag(name = "设备分类目录")
|
||||
public class DeviceCategoryController {
|
||||
@Tag(name = "产品分类管理")
|
||||
@AllArgsConstructor
|
||||
@Resource(id="device-category",name = "产品分类")
|
||||
public class DeviceCategoryController implements ReactiveServiceCrudController<DeviceCategoryEntity,String> {
|
||||
|
||||
|
||||
static List<DeviceCategory> statics;
|
||||
|
||||
|
||||
static void rebuild(String parentId, List<DeviceCategory> children) {
|
||||
if (children == null) {
|
||||
return;
|
||||
}
|
||||
for (DeviceCategory child : children) {
|
||||
String id = child.getId();
|
||||
child.setId(parentId + "|" + id + "|");
|
||||
child.setParentId(parentId + "|");
|
||||
rebuild(parentId + "|" + id, child.getChildren());
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
ClassPathResource resource = new ClassPathResource("device-category.json");
|
||||
String json = StreamUtils.copyToString(resource.getInputStream(), StandardCharsets.UTF_8);
|
||||
|
||||
List<DeviceCategory> all = JSON.parseArray(json, DeviceCategory.class);
|
||||
|
||||
List<DeviceCategory> root = TreeSupportEntity.list2tree(all, DeviceCategory::setChildren);
|
||||
|
||||
for (DeviceCategory category : root) {
|
||||
String id = category.getId();
|
||||
|
||||
category.setId("|" + id + "|");
|
||||
category.setParentId("|" + category.getParentId() + "|");
|
||||
rebuild("|" + id, category.getChildren());
|
||||
}
|
||||
|
||||
statics = all;
|
||||
|
||||
} catch (Exception e) {
|
||||
statics = new ArrayList<>();
|
||||
DeviceCategoryController.log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
private final DeviceCategoryService categoryService;
|
||||
|
||||
@GetMapping
|
||||
@Operation(summary = "获取全部分类目录")
|
||||
public Flux<DeviceCategory> getAllCategory() {
|
||||
return Flux.fromIterable(statics);
|
||||
@QueryNoPagingOperation(summary = "获取全部分类")
|
||||
@Authorize(merge = false)
|
||||
public Flux<DeviceCategoryEntity> getAllCategory(@Parameter(hidden = true) QueryParamEntity query) {
|
||||
return this
|
||||
.categoryService
|
||||
.createQuery()
|
||||
.setParam(query)
|
||||
.fetch();
|
||||
}
|
||||
|
||||
@GetMapping("/_query/no-paging")
|
||||
@Operation(summary = "获取全部分类目录")
|
||||
public Flux<DeviceCategory> getAllCategory2() {
|
||||
return Flux.fromIterable(statics);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/_tree")
|
||||
@Operation(summary = "获取全部分类目录(树结构)")
|
||||
public Flux<DeviceCategory> getAllCategoryTree() {
|
||||
return Flux.fromIterable(TreeSupportEntity.list2tree(statics, DeviceCategory::setChildren));
|
||||
@QueryNoPagingOperation(summary = "获取全部分类(树结构)")
|
||||
@Authorize(merge = false)
|
||||
public Flux<DeviceCategoryEntity> getAllCategoryTree(@Parameter(hidden = true) QueryParamEntity query) {
|
||||
return this
|
||||
.categoryService
|
||||
.createQuery()
|
||||
.setParam(query)
|
||||
.fetch()
|
||||
.collectList()
|
||||
.flatMapMany(all-> Flux.fromIterable(TreeSupportEntity.list2tree(all, DeviceCategoryEntity::setChildren)));
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/_tree")
|
||||
@QueryNoPagingOperation(summary = "获取全部分类(树结构)")
|
||||
@Authorize(merge = false)
|
||||
public Flux<DeviceCategoryEntity> getAllCategoryTreeByQueryParam(@RequestBody Mono<QueryParamEntity> query) {
|
||||
return this
|
||||
.categoryService
|
||||
.query(query)
|
||||
.collectList()
|
||||
.flatMapMany(all-> Flux.fromIterable(TreeSupportEntity.list2tree(all, DeviceCategoryEntity::setChildren)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReactiveCrudService<DeviceCategoryEntity, String> getService() {
|
||||
return categoryService;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,11 +7,13 @@ import io.swagger.v3.oas.annotations.Parameter;
|
|||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.Getter;
|
||||
import org.hswebframework.utils.StringUtils;
|
||||
import org.hswebframework.web.api.crud.entity.QueryParamEntity;
|
||||
import org.hswebframework.web.authorization.annotation.Authorize;
|
||||
import org.hswebframework.web.authorization.annotation.QueryAction;
|
||||
import org.hswebframework.web.authorization.annotation.Resource;
|
||||
import org.hswebframework.web.authorization.annotation.SaveAction;
|
||||
import org.hswebframework.web.crud.web.reactive.ReactiveServiceCrudController;
|
||||
import org.hswebframework.web.exception.BusinessException;
|
||||
import org.jetlinks.community.device.entity.ProtocolSupportEntity;
|
||||
import org.jetlinks.community.device.service.LocalProtocolSupportService;
|
||||
import org.jetlinks.community.device.web.protocol.ProtocolDetail;
|
||||
|
|
@ -19,6 +21,7 @@ import org.jetlinks.community.device.web.protocol.ProtocolInfo;
|
|||
import org.jetlinks.community.device.web.protocol.TransportInfo;
|
||||
import org.jetlinks.community.device.web.request.ProtocolDecodeRequest;
|
||||
import org.jetlinks.community.device.web.request.ProtocolEncodeRequest;
|
||||
import org.jetlinks.community.protocol.TransportDetail;
|
||||
import org.jetlinks.core.ProtocolSupport;
|
||||
import org.jetlinks.core.ProtocolSupports;
|
||||
import org.jetlinks.core.message.codec.Transport;
|
||||
|
|
@ -32,7 +35,10 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.web.bind.annotation.*;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuple2;
|
||||
import reactor.util.function.Tuples;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
|
|
@ -174,4 +180,57 @@ public class ProtocolSupportController
|
|||
public Flux<ValueUnit> allUnits() {
|
||||
return Flux.fromIterable(ValueUnits.getAllUnit());
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/supports/{transport}")
|
||||
@Authorize(merge = false)
|
||||
@Operation(summary = "获取支持指定传输协议的消息协议")
|
||||
public Flux<ProtocolInfo> getSupportTransportProtocols(@PathVariable String transport,
|
||||
@Parameter(hidden = true) QueryParamEntity query) {
|
||||
return protocolSupports
|
||||
.getProtocols()
|
||||
.collectMap(ProtocolSupport::getId)
|
||||
.flatMapMany(protocols -> service.createQuery()
|
||||
.setParam(query)
|
||||
.fetch()
|
||||
.index()
|
||||
.flatMap(tp2 -> Mono
|
||||
.justOrEmpty(protocols.get(tp2.getT2().getId()))
|
||||
.filterWhen(support -> support
|
||||
.getSupportedTransport()
|
||||
.filter(t -> t.isSame(transport))
|
||||
.hasElements())
|
||||
.map(ProtocolInfo::of)
|
||||
.map(protocolInfo -> Tuples.of(tp2.getT1(), protocolInfo))))
|
||||
.sort(Comparator.comparingLong(Tuple2::getT1))
|
||||
.map(Tuple2::getT2);
|
||||
}
|
||||
|
||||
@GetMapping("/{id}/transport/{transport}")
|
||||
@Authorize(merge = false)
|
||||
@Operation(summary = "获取消息协议对应的传输协议信息")
|
||||
public Mono<TransportDetail> getTransportDetail(@PathVariable @Parameter(description = "协议ID") String id,
|
||||
@PathVariable @Parameter(description = "传输协议") String transport) {
|
||||
return protocolSupports
|
||||
.getProtocol(id)
|
||||
.onErrorMap(e -> new BusinessException("error.unable_to_load_protocol_by_access_id", 404, id))
|
||||
.flatMapMany(protocol -> protocol
|
||||
.getSupportedTransport()
|
||||
.filter(trans -> trans.isSame(transport))
|
||||
.distinct()
|
||||
.flatMap(_transport -> TransportDetail.of(protocol, _transport)))
|
||||
.singleOrEmpty();
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/{id}/detail")
|
||||
@QueryAction
|
||||
@Operation(summary = "获取协议详情")
|
||||
public Mono<ProtocolDetail> protocolDetail(@PathVariable String id) {
|
||||
return protocolSupports
|
||||
.getProtocol(id)
|
||||
.onErrorMap(e -> new BusinessException("error.unable_to_load_protocol_by_access_id", 404, id))
|
||||
.flatMap(ProtocolDetail::of);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue