mirror of
https://github.com/hs-web/hsweb-framework.git
synced 2026-09-03 06:35:25 +08:00
refactor: 优化
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
*
|
||||
* * Copyright 2020 http://www.hswebframework.org
|
||||
* *
|
||||
* * Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* * you may not use this file except in compliance with the License.
|
||||
* * You may obtain a copy of the License at
|
||||
* *
|
||||
* * http://www.apache.org/licenses/LICENSE-2.0
|
||||
* *
|
||||
* * Unless required by applicable law or agreed to in writing, software
|
||||
* * distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* * See the License for the specific language governing permissions and
|
||||
* * limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
package org.hswebframework.web.api.crud.entity;
|
||||
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
import org.hswebframework.ezorm.rdb.mapping.annotation.Comment;
|
||||
|
||||
import javax.persistence.Column;
|
||||
|
||||
/**
|
||||
* 支持树形结构,排序的实体类,要使用树形结构,排序功能的实体类直接继承该类
|
||||
*/
|
||||
@Getter
|
||||
@Setter
|
||||
public abstract class ExtendableTreeSortSupportEntity<PK> extends ExtendableEntity<PK>
|
||||
implements TreeSortSupportEntity<PK> {
|
||||
/**
|
||||
* 父级类别
|
||||
*/
|
||||
@Column(name = "parent_id", length = 64)
|
||||
@Comment("父级ID")
|
||||
@Schema(description = "父节点ID")
|
||||
private PK parentId;
|
||||
|
||||
/**
|
||||
* 树结构编码,用于快速查找, 每一层由4位字符组成,用-分割
|
||||
* 如第一层:0001 第二层:0001-0001 第三层:0001-0001-0001
|
||||
*/
|
||||
@Column(name = "path", length = 128)
|
||||
@Comment("树路径")
|
||||
@Schema(description = "树结构路径")
|
||||
@Length(max = 128, message = "目录层级太深")
|
||||
private String path;
|
||||
|
||||
/**
|
||||
* 排序索引
|
||||
*/
|
||||
@Column(name = "sort_index", precision = 32)
|
||||
@Comment("排序序号")
|
||||
@Schema(description = "排序序号")
|
||||
private Long sortIndex;
|
||||
|
||||
@Column(name = "_level", precision = 32)
|
||||
@Comment("树层级")
|
||||
@Schema(description = "树层级")
|
||||
private Integer level;
|
||||
|
||||
|
||||
}
|
||||
@@ -78,37 +78,40 @@ public class TreeUtils {
|
||||
(helper, node) -> {
|
||||
PK parentId = parentIdGetter.apply(node);
|
||||
return ObjectUtils.isEmpty(parentId)
|
||||
|| helper.getNode(parentId) == null;
|
||||
|| helper.getNode(parentId) == null;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表结构转为树结构,并返回根节点集合
|
||||
*
|
||||
* @param dataList 数据集合
|
||||
* @param childConsumer 子节点消费接口,用于设置子节点
|
||||
* @param predicateFunction 根节点判断函数,传入helper,获取一个判断是否为跟节点的函数
|
||||
* @param <N> 元素类型
|
||||
* @param <PK> 主键类型
|
||||
* @param dataList 数据集合
|
||||
* @param childConsumer 子节点消费接口,用于设置子节点
|
||||
* @param rootPredicate 根节点判断函数,传入helper,获取一个判断是否为根节点的函数
|
||||
* @param <N> 元素类型
|
||||
* @param <PK> 主键类型
|
||||
* @return 根节点集合
|
||||
*/
|
||||
public static <N, PK> List<N> list2tree(Collection<N> dataList,
|
||||
Function<N, PK> idGetter,
|
||||
Function<N, PK> parentIdGetter,
|
||||
BiConsumer<N, List<N>> childConsumer,
|
||||
BiPredicate<TreeSupportEntity.TreeHelper<N, PK>, N> predicateFunction) {
|
||||
BiPredicate<TreeSupportEntity.TreeHelper<N, PK>, N> rootPredicate) {
|
||||
Objects.requireNonNull(dataList, "source list can not be null");
|
||||
Objects.requireNonNull(childConsumer, "child consumer can not be null");
|
||||
Objects.requireNonNull(predicateFunction, "root predicate function can not be null");
|
||||
|
||||
Objects.requireNonNull(rootPredicate, "root predicate function can not be null");
|
||||
int size = dataList.size();
|
||||
if (size == 0) {
|
||||
return new ArrayList<>(0);
|
||||
}
|
||||
// id,node
|
||||
Map<PK, N> cache = Maps.newHashMapWithExpectedSize(dataList.size());
|
||||
Map<PK, N> cache = Maps.newHashMapWithExpectedSize(size);
|
||||
// parentId,children
|
||||
Map<PK, List<N>> treeCache = dataList
|
||||
.stream()
|
||||
.peek(node -> cache.put(idGetter.apply(node), node))
|
||||
.filter(e -> parentIdGetter.apply(e) != null)
|
||||
.collect(Collectors.groupingBy(parentIdGetter));
|
||||
.stream()
|
||||
.peek(node -> cache.put(idGetter.apply(node), node))
|
||||
.filter(e -> parentIdGetter.apply(e) != null)
|
||||
.collect(Collectors.groupingBy(parentIdGetter));
|
||||
|
||||
TreeSupportEntity.TreeHelper<N, PK> helper = new TreeSupportEntity.TreeHelper<N, PK>() {
|
||||
@Override
|
||||
@@ -122,13 +125,18 @@ public class TreeUtils {
|
||||
}
|
||||
};
|
||||
|
||||
return dataList
|
||||
.stream()
|
||||
//设置每个节点的子节点
|
||||
.peek(node -> childConsumer.accept(node, treeCache.get(idGetter.apply(node))))
|
||||
//获取根节点
|
||||
.filter(node -> predicateFunction.test(helper, node))
|
||||
.collect(Collectors.toList());
|
||||
List<N> list = new ArrayList<>(treeCache.size());
|
||||
|
||||
for (N node : dataList) {
|
||||
//设置每个节点的子节点
|
||||
childConsumer.accept(node, treeCache.get(idGetter.apply(node)));
|
||||
|
||||
//获取根节点
|
||||
if (rootPredicate.test(helper, node)) {
|
||||
list.add(node);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ import java.util.stream.Collectors;
|
||||
* @see GenericReactiveTreeSupportCrudService
|
||||
*/
|
||||
public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K>, K>
|
||||
extends ReactiveCrudService<E, K> {
|
||||
extends ReactiveCrudService<E, K> {
|
||||
|
||||
/**
|
||||
* 动态查询并将查询结构转为树形结构
|
||||
@@ -54,10 +54,10 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
|
||||
@Transactional(readOnly = true, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<List<E>> queryResultToTree(QueryParamEntity paramEntity) {
|
||||
return query(paramEntity)
|
||||
.collectList()
|
||||
.map(list -> TreeSupportEntity.list2tree(list,
|
||||
this::setChildren,
|
||||
this::createRootNodePredicate));
|
||||
.collectList()
|
||||
.map(list -> TreeSupportEntity.list2tree(list,
|
||||
this::setChildren,
|
||||
this::createRootNodePredicate));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,55 +69,78 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
|
||||
@Transactional(readOnly = true, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<List<E>> queryIncludeChildrenTree(QueryParamEntity paramEntity) {
|
||||
return queryIncludeChildren(paramEntity)
|
||||
.collectList()
|
||||
.map(list -> TreeSupportEntity.list2tree(list,
|
||||
this::setChildren,
|
||||
this::createRootNodePredicate));
|
||||
.collectList()
|
||||
.map(list -> TreeSupportEntity.list2tree(list,
|
||||
this::setChildren,
|
||||
this::createRootNodePredicate));
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询指定ID的实体以及对应的全部子节点
|
||||
*
|
||||
* @param idList ID集合
|
||||
* @return 树形结构
|
||||
* @return 包含子节点的所有节点
|
||||
*/
|
||||
@Transactional(readOnly = true, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Flux<E> queryIncludeChildren(Collection<K> idList) {
|
||||
Set<String> duplicateCheck = new HashSet<>();
|
||||
return queryIncludeChildren(findById(idList));
|
||||
}
|
||||
|
||||
return findById(idList)
|
||||
.concatMap(e -> !StringUtils.hasText(e.getPath()) || !duplicateCheck.add(e.getPath())
|
||||
? Mono.just(e)
|
||||
: createQuery()
|
||||
.where()
|
||||
//使用path快速查询
|
||||
.like$("path", e.getPath())
|
||||
.fetch(),
|
||||
Integer.MAX_VALUE)
|
||||
.distinct(TreeSupportEntity::getId);
|
||||
/**
|
||||
* 根据实体流查询全部子节点(包含原节点)
|
||||
*
|
||||
* @param entities 实体流
|
||||
* @return 包含子节点的所有节点
|
||||
* @since 4.0.18
|
||||
*/
|
||||
@Transactional(readOnly = true, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Flux<E> queryIncludeChildren(Flux<E> entities) {
|
||||
Set<String> duplicateCheck = new HashSet<>();
|
||||
return entities
|
||||
.concatMap(e -> !StringUtils.hasText(e.getPath()) || !duplicateCheck.add(e.getPath())
|
||||
? Mono.just(e)
|
||||
: createQuery()
|
||||
.where()
|
||||
//使用path快速查询
|
||||
.like$("path", e.getPath())
|
||||
.fetch(),
|
||||
Integer.MAX_VALUE)
|
||||
.distinct(TreeSupportEntity::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询指定ID的实体以及对应的全部父节点
|
||||
*
|
||||
* @param idList ID集合
|
||||
* @return 树形结构
|
||||
* @return 包含父节点的所有节点
|
||||
*/
|
||||
@Transactional(readOnly = true, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Flux<E> queryIncludeParent(Collection<K> idList) {
|
||||
return queryIncludeParent(findById(idList));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据实体流查询全部父节点(包含原节点)
|
||||
*
|
||||
* @param entities 实体流
|
||||
* @return 包含父节点的所有节点
|
||||
* @since 4.0.18
|
||||
*/
|
||||
@Transactional(readOnly = true, transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Flux<E> queryIncludeParent(Flux<E> entities) {
|
||||
Set<String> duplicateCheck = new HashSet<>();
|
||||
|
||||
return findById(idList)
|
||||
.concatMap(e -> !StringUtils.hasText(e.getPath()) || !duplicateCheck.add(e.getPath())
|
||||
? Mono.just(e)
|
||||
: createQuery()
|
||||
.where()
|
||||
//where ? like path and path !='' and path not null
|
||||
.accept(Terms.Like.reversal("path", e.getPath(), false, true))
|
||||
.notEmpty("path")
|
||||
.notNull("path")
|
||||
.fetch(), Integer.MAX_VALUE)
|
||||
.distinct(TreeSupportEntity::getId);
|
||||
return entities
|
||||
.concatMap(e -> !StringUtils.hasText(e.getPath()) || !duplicateCheck.add(e.getPath())
|
||||
? Mono.just(e)
|
||||
: createQuery()
|
||||
.where()
|
||||
//where ? like path and path !='' and path not null
|
||||
.accept(Terms.Like.reversal("path", e.getPath(), false, true))
|
||||
.notEmpty("path")
|
||||
.notNull("path")
|
||||
.fetch(), Integer.MAX_VALUE)
|
||||
.distinct(TreeSupportEntity::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,23 +154,23 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
|
||||
Set<String> duplicateCheck = new HashSet<>();
|
||||
|
||||
return query(queryParam)
|
||||
.concatMap(e -> !StringUtils.hasText(e.getPath()) || !duplicateCheck.add(e.getPath())
|
||||
? Mono.just(e)
|
||||
: createQuery()
|
||||
.as(q -> {
|
||||
if (CollectionUtils.isNotEmpty(queryParam.getIncludes())) {
|
||||
q.select(queryParam.getIncludes().toArray(new String[0]));
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(queryParam.getExcludes())) {
|
||||
q.selectExcludes(queryParam.getExcludes().toArray(new String[0]));
|
||||
}
|
||||
return q;
|
||||
})
|
||||
.where()
|
||||
.like$("path", e.getPath())
|
||||
.fetch()
|
||||
,Integer.MAX_VALUE)
|
||||
.distinct(TreeSupportEntity::getId);
|
||||
.concatMap(e -> !StringUtils.hasText(e.getPath()) || !duplicateCheck.add(e.getPath())
|
||||
? Mono.just(e)
|
||||
: createQuery()
|
||||
.as(q -> {
|
||||
if (CollectionUtils.isNotEmpty(queryParam.getIncludes())) {
|
||||
q.select(queryParam.getIncludes().toArray(new String[0]));
|
||||
}
|
||||
if (CollectionUtils.isNotEmpty(queryParam.getExcludes())) {
|
||||
q.selectExcludes(queryParam.getExcludes().toArray(new String[0]));
|
||||
}
|
||||
return q;
|
||||
})
|
||||
.where()
|
||||
.like$("path", e.getPath())
|
||||
.fetch()
|
||||
, Integer.MAX_VALUE)
|
||||
.distinct(TreeSupportEntity::getId);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,12 +189,12 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> insertBatch(Publisher<? extends Collection<E>> entityPublisher) {
|
||||
return this
|
||||
.getRepository()
|
||||
.insertBatch(new TreeSortServiceHelper<>(this)
|
||||
.prepare(Flux.from(entityPublisher)
|
||||
.flatMapIterable(Function.identity()))
|
||||
// .doOnNext(e -> e.tryValidate(CreateGroup.class))
|
||||
.buffer(getBufferSize()));
|
||||
.getRepository()
|
||||
.insertBatch(new TreeSortServiceHelper<>(this)
|
||||
.prepare(Flux.from(entityPublisher)
|
||||
.flatMapIterable(Function.identity()))
|
||||
// .doOnNext(e -> e.tryValidate(CreateGroup.class))
|
||||
.buffer(getBufferSize()));
|
||||
}
|
||||
|
||||
default int getBufferSize() {
|
||||
@@ -181,7 +204,7 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
|
||||
@Deprecated
|
||||
default Mono<E> applyTreeProperty(E ele) {
|
||||
if (StringUtils.hasText(ele.getPath()) ||
|
||||
ObjectUtils.isEmpty(ele.getParentId())) {
|
||||
ObjectUtils.isEmpty(ele.getParentId())) {
|
||||
return Mono.just(ele);
|
||||
}
|
||||
|
||||
@@ -198,57 +221,57 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
|
||||
return Mono.empty();
|
||||
}
|
||||
return this
|
||||
.queryIncludeChildren(Collections.singletonList(id))
|
||||
.doOnNext(e -> {
|
||||
if (Objects.equals(ele.getParentId(), e.getId())) {
|
||||
throw new ValidationException.NoStackTrace("parentId", "error.tree_entity_cyclic_dependency");
|
||||
}
|
||||
})
|
||||
.then(Mono.just(ele));
|
||||
.queryIncludeChildren(Collections.singletonList(id))
|
||||
.doOnNext(e -> {
|
||||
if (Objects.equals(ele.getParentId(), e.getId())) {
|
||||
throw new ValidationException.NoStackTrace("parentId", "error.tree_entity_cyclic_dependency");
|
||||
}
|
||||
})
|
||||
.then(Mono.just(ele));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
default Mono<Collection<E>> checkParentId(Collection<E> source) {
|
||||
|
||||
Set<K> idSet = source
|
||||
.stream()
|
||||
.map(TreeSupportEntity::getId)
|
||||
.filter(e -> !ObjectUtils.isEmpty(e))
|
||||
.collect(Collectors.toSet());
|
||||
.stream()
|
||||
.map(TreeSupportEntity::getId)
|
||||
.filter(e -> !ObjectUtils.isEmpty(e))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (idSet.isEmpty()) {
|
||||
return Mono.just(source);
|
||||
}
|
||||
|
||||
Set<K> readyToCheck = source
|
||||
.stream()
|
||||
.map(TreeSupportEntity::getParentId)
|
||||
.filter(e -> !ObjectUtils.isEmpty(e) && !idSet.contains(e))
|
||||
.collect(Collectors.toSet());
|
||||
.stream()
|
||||
.map(TreeSupportEntity::getParentId)
|
||||
.filter(e -> !ObjectUtils.isEmpty(e) && !idSet.contains(e))
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
if (readyToCheck.isEmpty()) {
|
||||
return Mono.just(source);
|
||||
}
|
||||
|
||||
return this
|
||||
.createQuery()
|
||||
.select("id")
|
||||
.in("id", readyToCheck)
|
||||
.fetch()
|
||||
.doOnNext(e -> readyToCheck.remove(e.getId()))
|
||||
.then(Mono.fromSupplier(() -> {
|
||||
if (!readyToCheck.isEmpty()) {
|
||||
throw new ValidationException(
|
||||
.createQuery()
|
||||
.select("id")
|
||||
.in("id", readyToCheck)
|
||||
.fetch()
|
||||
.doOnNext(e -> readyToCheck.remove(e.getId()))
|
||||
.then(Mono.fromSupplier(() -> {
|
||||
if (!readyToCheck.isEmpty()) {
|
||||
throw new ValidationException(
|
||||
"error.tree_entity_parent_id_not_exist",
|
||||
Collections.singletonList(
|
||||
new ValidationException.Detail(
|
||||
"parentId",
|
||||
"error.tree_entity_parent_id_not_exist",
|
||||
Collections.singletonList(
|
||||
new ValidationException.Detail(
|
||||
"parentId",
|
||||
"error.tree_entity_parent_id_not_exist",
|
||||
readyToCheck))
|
||||
);
|
||||
}
|
||||
return source;
|
||||
}));
|
||||
readyToCheck))
|
||||
);
|
||||
}
|
||||
return source;
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
@@ -274,14 +297,14 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Throwable.class,
|
||||
transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<SaveResult> save(Publisher<E> entityPublisher) {
|
||||
return new TreeSortServiceHelper<>(this)
|
||||
.prepare(Flux.from(entityPublisher))
|
||||
.prepare(Flux.from(entityPublisher))
|
||||
// .doOnNext(e -> e.tryValidate(CreateGroup.class))
|
||||
.buffer(getBufferSize())
|
||||
.flatMap(this.getRepository()::save)
|
||||
.reduce(SaveResult::merge);
|
||||
.buffer(getBufferSize())
|
||||
.flatMap(this.getRepository()::save)
|
||||
.reduce(SaveResult::merge);
|
||||
|
||||
}
|
||||
|
||||
@@ -306,12 +329,12 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> updateById(K id, Mono<E> entityPublisher) {
|
||||
return this
|
||||
.findById(id)
|
||||
.map(e -> this
|
||||
.save(entityPublisher.doOnNext(data -> data.setId(id)))
|
||||
.map(SaveResult::getTotal))
|
||||
.defaultIfEmpty(Mono.just(0))
|
||||
.flatMap(Function.identity());
|
||||
.findById(id)
|
||||
.map(e -> this
|
||||
.save(entityPublisher.doOnNext(data -> data.setId(id)))
|
||||
.map(SaveResult::getTotal))
|
||||
.defaultIfEmpty(Mono.just(0))
|
||||
.flatMap(Function.identity());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -324,11 +347,11 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
|
||||
@Transactional(transactionManager = TransactionManagers.reactiveTransactionManager)
|
||||
default Mono<Integer> deleteById(Publisher<K> idPublisher) {
|
||||
return this
|
||||
.findById(Flux.from(idPublisher))
|
||||
.concatMap(e -> StringUtils.hasText(e.getPath())
|
||||
? getRepository().createDelete().where().like$(e::getPath).execute()
|
||||
: getRepository().deleteById(e.getId()),Integer.MAX_VALUE)
|
||||
.as(MathFlux::sumInt);
|
||||
.findById(Flux.from(idPublisher))
|
||||
.concatMap(e -> StringUtils.hasText(e.getPath())
|
||||
? getRepository().createDelete().where().like$(e::getPath).execute()
|
||||
: getRepository().deleteById(e.getId()), Integer.MAX_VALUE)
|
||||
.as(MathFlux::sumInt);
|
||||
}
|
||||
|
||||
IDGenerator<K> getIDGenerator();
|
||||
@@ -360,18 +383,18 @@ public interface ReactiveTreeSortEntityService<E extends TreeSortSupportEntity<K
|
||||
@SuppressWarnings("all")
|
||||
default ReactiveDelete createDelete() {
|
||||
return ReactiveCrudService.super
|
||||
.createDelete()
|
||||
.onExecute((delete, executor) -> this
|
||||
.queryIncludeChildren(delete.toQueryParam(QueryParamEntity::new)
|
||||
.<QueryParamEntity>includes("id", "path", "parentId"))
|
||||
.map(TreeSupportEntity::getId)
|
||||
.buffer(200)
|
||||
.concatMap(list -> getRepository()
|
||||
.createDelete()
|
||||
.where()
|
||||
.in("id", list)
|
||||
.execute(), Integer.MAX_VALUE)
|
||||
//.concatWith(executor)
|
||||
.reduce(0, Math::addExact));
|
||||
.createDelete()
|
||||
.onExecute((delete, executor) -> this
|
||||
.queryIncludeChildren(delete.toQueryParam(QueryParamEntity::new)
|
||||
.<QueryParamEntity>includes("id", "path", "parentId"))
|
||||
.map(TreeSupportEntity::getId)
|
||||
.buffer(200)
|
||||
.concatMap(list -> getRepository()
|
||||
.createDelete()
|
||||
.where()
|
||||
.in("id", list)
|
||||
.execute(), Integer.MAX_VALUE)
|
||||
//.concatWith(executor)
|
||||
.reduce(0, Math::addExact));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,20 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
public class FastBeanCopierTest {
|
||||
|
||||
|
||||
@Test
|
||||
public void testExtendableToExtendable() {
|
||||
ExtendableEntity source = new ExtendableEntity();
|
||||
source.setName("test");
|
||||
source.setExtension("age", 123);
|
||||
source.setExtension("color", Color.RED);
|
||||
|
||||
ExtendableEntity e = FastBeanCopier.copy(source, new ExtendableEntity());
|
||||
|
||||
Assert.assertEquals(source.getName(), e.getName());
|
||||
Assert.assertEquals(source.getExtension("age"), e.getExtension("age"));
|
||||
Assert.assertEquals(source.getExtension("color"), e.getExtension("color"));
|
||||
|
||||
}
|
||||
@Test
|
||||
public void testToExtendable() {
|
||||
Source source = new Source();
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.util.StringUtils;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.util.function.Tuples;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
@@ -33,7 +34,7 @@ import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
public class DefaultReactiveAuthenticationInitializeService
|
||||
implements ReactiveAuthenticationInitializeService {
|
||||
implements ReactiveAuthenticationInitializeService {
|
||||
|
||||
@Autowired
|
||||
private ReactiveUserService userService;
|
||||
@@ -63,25 +64,25 @@ public class DefaultReactiveAuthenticationInitializeService
|
||||
return userEntityMono.flatMap(user -> {
|
||||
SimpleAuthentication authentication = new SimpleAuthentication();
|
||||
authentication.setUser(SimpleUser
|
||||
.builder()
|
||||
.id(user.getId())
|
||||
.name(user.getName())
|
||||
.username(user.getUsername())
|
||||
.userType(user.getType())
|
||||
.build());
|
||||
.builder()
|
||||
.id(user.getId())
|
||||
.name(user.getName())
|
||||
.username(user.getUsername())
|
||||
.userType(user.getType())
|
||||
.build());
|
||||
|
||||
return initPermission(authentication)
|
||||
.defaultIfEmpty(authentication)
|
||||
.onErrorResume(err -> {
|
||||
log.warn(err.getMessage(), err);
|
||||
return Mono.just(authentication);
|
||||
})
|
||||
.flatMap(auth -> {
|
||||
AuthorizationInitializeEvent event = new AuthorizationInitializeEvent(auth);
|
||||
return event
|
||||
.publish(eventPublisher)
|
||||
.then(Mono.fromSupplier(event::getAuthentication));
|
||||
});
|
||||
.defaultIfEmpty(authentication)
|
||||
.onErrorResume(err -> {
|
||||
log.warn(err.getMessage(), err);
|
||||
return Mono.just(authentication);
|
||||
})
|
||||
.flatMap(auth -> {
|
||||
AuthorizationInitializeEvent event = new AuthorizationInitializeEvent(auth);
|
||||
return event
|
||||
.publish(eventPublisher)
|
||||
.then(Mono.fromSupplier(event::getAuthentication));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -90,26 +91,28 @@ public class DefaultReactiveAuthenticationInitializeService
|
||||
.filter(dimension -> dimension.getType() != null)
|
||||
.groupBy(d -> d.getType().getId(), (Function<Dimension, Object>) Dimension::getId)
|
||||
.flatMap(group ->
|
||||
group.collectList()
|
||||
.flatMapMany(list -> settingRepository
|
||||
.createQuery()
|
||||
.where(AuthorizationSettingEntity::getState, 1)
|
||||
.and(AuthorizationSettingEntity::getDimensionType, group.key())
|
||||
.in(AuthorizationSettingEntity::getDimensionTarget, list)
|
||||
.fetch()));
|
||||
group.collectList()
|
||||
.flatMapMany(list -> settingRepository
|
||||
.createQuery()
|
||||
.where(AuthorizationSettingEntity::getState, 1)
|
||||
.and(AuthorizationSettingEntity::getDimensionType, group.key())
|
||||
.in(AuthorizationSettingEntity::getDimensionTarget, list)
|
||||
.fetch()));
|
||||
}
|
||||
|
||||
protected Mono<Authentication> initPermission(SimpleAuthentication authentication) {
|
||||
return Flux.fromIterable(dimensionProviders)
|
||||
.flatMap(provider -> provider.getDimensionByUserId(authentication.getUser().getId()))
|
||||
.cast(Dimension.class)
|
||||
//去重?还是合并?
|
||||
.distinct(dis -> Tuples.of(dis.getType().getId(), dis.getId()))
|
||||
.doOnNext(authentication::addDimension)
|
||||
.collectList()
|
||||
.then(Mono.defer(() -> Mono
|
||||
.zip(getAllPermission(),
|
||||
getSettings(authentication.getDimensions()).collect(Collectors.groupingBy(AuthorizationSettingEntity::getPermission)),
|
||||
(_p, _s) -> handlePermission(authentication, _p, _s)
|
||||
)));
|
||||
.zip(getAllPermission(),
|
||||
getSettings(authentication.getDimensions()).collect(Collectors.groupingBy(AuthorizationSettingEntity::getPermission)),
|
||||
(_p, _s) -> handlePermission(authentication, _p, _s)
|
||||
)));
|
||||
|
||||
}
|
||||
|
||||
@@ -145,9 +148,9 @@ public class DefaultReactiveAuthenticationInitializeService
|
||||
.stream()
|
||||
.map(conf -> {
|
||||
DataAccessConfig config = builderFactory
|
||||
.create()
|
||||
.fromMap(conf.toMap())
|
||||
.build();
|
||||
.create()
|
||||
.fromMap(conf.toMap())
|
||||
.build();
|
||||
if (config == null) {
|
||||
log.warn("unsupported data access:{}", conf.toMap());
|
||||
}
|
||||
@@ -205,11 +208,11 @@ public class DefaultReactiveAuthenticationInitializeService
|
||||
protected Mono<Map<String, PermissionEntity>> getAllPermission() {
|
||||
|
||||
return permissionRepository
|
||||
.createQuery()
|
||||
.where(PermissionEntity::getStatus, 1)
|
||||
.fetch()
|
||||
.collect(Collectors.toMap(PermissionEntity::getId, Function.identity()))
|
||||
.switchIfEmpty(Mono.just(Collections.emptyMap()));
|
||||
.createQuery()
|
||||
.where(PermissionEntity::getStatus, 1)
|
||||
.fetch()
|
||||
.collect(Collectors.toMap(PermissionEntity::getId, Function.identity()))
|
||||
.switchIfEmpty(Mono.just(Collections.emptyMap()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user