|
@@ -1,9 +1,11 @@
|
|
|
package org.hswebframework.web.crud.events;
|
|
|
|
|
|
|
|
|
+import lombok.AllArgsConstructor;
|
|
|
import org.apache.commons.collections.CollectionUtils;
|
|
|
import org.hswebframework.ezorm.core.param.QueryParam;
|
|
|
import org.hswebframework.ezorm.rdb.events.*;
|
|
|
+import org.hswebframework.ezorm.rdb.events.EventType;
|
|
|
import org.hswebframework.ezorm.rdb.mapping.*;
|
|
|
import org.hswebframework.ezorm.rdb.mapping.events.MappingContextKeys;
|
|
|
import org.hswebframework.ezorm.rdb.mapping.events.MappingEventTypes;
|
|
@@ -31,10 +33,12 @@ import java.util.concurrent.atomic.AtomicReference;
|
|
|
import java.util.function.BiFunction;
|
|
|
|
|
|
@SuppressWarnings("all")
|
|
|
+@AllArgsConstructor
|
|
|
public class EntityEventListener implements EventListener {
|
|
|
|
|
|
- @Autowired
|
|
|
- ApplicationEventPublisher eventPublisher;
|
|
|
+ private final ApplicationEventPublisher eventPublisher;
|
|
|
+
|
|
|
+ private final EntityEventListenerConfigure listenerConfigure;
|
|
|
|
|
|
@Override
|
|
|
public String getId() {
|
|
@@ -53,36 +57,59 @@ public class EntityEventListener implements EventListener {
|
|
|
return;
|
|
|
}
|
|
|
EntityColumnMapping mapping = context.get(MappingContextKeys.columnMapping).orElse(null);
|
|
|
+ Class<Entity> entityType;
|
|
|
+
|
|
|
if (mapping == null ||
|
|
|
- !Entity.class.isAssignableFrom(mapping.getEntityType()) ||
|
|
|
- mapping.getEntityType().getAnnotation(EnableEntityEvent.class) == null) {
|
|
|
+ !Entity.class.isAssignableFrom(entityType = (Class) mapping.getEntityType()) ||
|
|
|
+ !listenerConfigure.isEnabled(entityType)) {
|
|
|
return;
|
|
|
}
|
|
|
+
|
|
|
if (type == MappingEventTypes.select_before) {
|
|
|
handleQueryBefore(mapping, context);
|
|
|
}
|
|
|
if (type == MappingEventTypes.insert_before) {
|
|
|
boolean single = context.get(MappingContextKeys.type).map("single"::equals).orElse(false);
|
|
|
if (single) {
|
|
|
- handleSingleOperation(mapping.getEntityType(), context, EntityBeforeCreateEvent::new, EntityCreatedEvent::new);
|
|
|
+ handleSingleOperation(mapping.getEntityType(),
|
|
|
+ EntityEventType.create,
|
|
|
+ context,
|
|
|
+ EntityPrepareCreateEvent::new,
|
|
|
+ EntityBeforeCreateEvent::new,
|
|
|
+ EntityCreatedEvent::new);
|
|
|
} else {
|
|
|
- handleBatchOperation(mapping.getEntityType(), context, EntityBeforeCreateEvent::new, EntityCreatedEvent::new);
|
|
|
+ handleBatchOperation(mapping.getEntityType(),
|
|
|
+ EntityEventType.save,
|
|
|
+ context,
|
|
|
+ EntityPrepareSaveEvent::new,
|
|
|
+ EntityBeforeCreateEvent::new,
|
|
|
+ EntityCreatedEvent::new);
|
|
|
}
|
|
|
}
|
|
|
if (type == MappingEventTypes.save_before) {
|
|
|
boolean single = context.get(MappingContextKeys.type).map("single"::equals).orElse(false);
|
|
|
if (single) {
|
|
|
- handleSingleOperation(mapping.getEntityType(), context, EntityBeforeSaveEvent::new, EntitySavedEvent::new);
|
|
|
+ handleSingleOperation(mapping.getEntityType(),
|
|
|
+ EntityEventType.save,
|
|
|
+ context,
|
|
|
+
|
|
|
+ EntityPrepareSaveEvent::new,
|
|
|
+ EntityBeforeSaveEvent::new,
|
|
|
+ EntitySavedEvent::new);
|
|
|
} else {
|
|
|
- handleBatchOperation(mapping.getEntityType(), context, EntityBeforeSaveEvent::new, EntitySavedEvent::new);
|
|
|
+ handleBatchOperation(mapping.getEntityType(),
|
|
|
+ EntityEventType.save,
|
|
|
+ context,
|
|
|
+ EntityPrepareSaveEvent::new,
|
|
|
+ EntityBeforeSaveEvent::new,
|
|
|
+ EntitySavedEvent::new);
|
|
|
}
|
|
|
}
|
|
|
if (type == MappingEventTypes.update_before) {
|
|
|
handleUpdateBefore(context);
|
|
|
}
|
|
|
-
|
|
|
if (type == MappingEventTypes.delete_before) {
|
|
|
- handleDeleteBefore(context);
|
|
|
+ handleDeleteBefore(entityType, context);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -123,12 +150,13 @@ public class EntityEventListener implements EventListener {
|
|
|
.filter(Entity.class::isInstance)
|
|
|
.map(Entity.class::cast)
|
|
|
.orElseGet(() -> {
|
|
|
- return context.get(MappingContextKeys.updateColumnInstance)
|
|
|
- .map(map -> {
|
|
|
- return FastBeanCopier.copy(map, FastBeanCopier.copy(old, mapping.getEntityType()));
|
|
|
- })
|
|
|
- .map(Entity.class::cast)
|
|
|
- .orElse(null);
|
|
|
+ return context
|
|
|
+ .get(MappingContextKeys.updateColumnInstance)
|
|
|
+ .map(map -> {
|
|
|
+ return FastBeanCopier.copy(map, FastBeanCopier.copy(old, mapping.getEntityType()));
|
|
|
+ })
|
|
|
+ .map(Entity.class::cast)
|
|
|
+ .orElse(null);
|
|
|
});
|
|
|
if (newValue != null) {
|
|
|
FastBeanCopier.copy(old, newValue, FastBeanCopier.include(idColumn.getAlias()));
|
|
@@ -162,51 +190,81 @@ public class EntityEventListener implements EventListener {
|
|
|
EntityColumnMapping mapping = context
|
|
|
.get(MappingContextKeys.columnMapping)
|
|
|
.orElseThrow(UnsupportedOperationException::new);
|
|
|
-
|
|
|
+ Class entityType = (Class) mapping.getEntityType();
|
|
|
if (repo instanceof ReactiveRepository) {
|
|
|
|
|
|
context.get(MappingContextKeys.reactiveResultHolder)
|
|
|
.ifPresent(holder -> {
|
|
|
AtomicReference<Tuple2<List<Object>, List<Object>>> updated = new AtomicReference<>();
|
|
|
+ //prepare
|
|
|
+ if (isEnabled(entityType,
|
|
|
+ EntityEventType.modify,
|
|
|
+ EntityEventPhase.prepare,
|
|
|
+ EntityEventPhase.before,
|
|
|
+ EntityEventPhase.after)) {
|
|
|
+ holder.before(
|
|
|
+ ((ReactiveRepository<Object, ?>) repo)
|
|
|
+ .createQuery()
|
|
|
+ .setParam(update.toQueryParam())
|
|
|
+ .fetch()
|
|
|
+ .collectList()
|
|
|
+ .flatMap((list) -> {
|
|
|
+ List<Object> after = createAfterData(list, context);
|
|
|
+ updated.set(Tuples.of(list, after));
|
|
|
+ return sendUpdateEvent(list,
|
|
|
+ after,
|
|
|
+ entityType,
|
|
|
+ EntityPrepareModifyEvent::new);
|
|
|
|
|
|
- holder.after(v -> {
|
|
|
- return Mono.defer(() -> {
|
|
|
- Tuple2<List<Object>, List<Object>> _tmp = updated.getAndSet(null);
|
|
|
+ })
|
|
|
+ .then()
|
|
|
+ );
|
|
|
+ }
|
|
|
+ //before
|
|
|
+ if (isEnabled(entityType, EntityEventType.modify, EntityEventPhase.before)) {
|
|
|
+ holder.invoke(Mono.defer(() -> {
|
|
|
+ Tuple2<List<Object>, List<Object>> _tmp = updated.get();
|
|
|
if (_tmp != null) {
|
|
|
- return sendUpdateEvent(_tmp.getT1(), _tmp.getT2(), (Class) mapping.getEntityType(), EntityModifyEvent::new);
|
|
|
+ return sendUpdateEvent(_tmp.getT1(),
|
|
|
+ _tmp.getT2(),
|
|
|
+ entityType,
|
|
|
+ EntityBeforeModifyEvent::new);
|
|
|
}
|
|
|
return Mono.empty();
|
|
|
+ }));
|
|
|
+ }
|
|
|
+
|
|
|
+ //after
|
|
|
+ if (isEnabled(entityType, EntityEventType.modify, EntityEventPhase.after)) {
|
|
|
+ holder.after(v -> {
|
|
|
+ return Mono
|
|
|
+ .defer(() -> {
|
|
|
+ Tuple2<List<Object>, List<Object>> _tmp = updated.getAndSet(null);
|
|
|
+ if (_tmp != null) {
|
|
|
+ return sendUpdateEvent(_tmp.getT1(),
|
|
|
+ _tmp.getT2(),
|
|
|
+ entityType,
|
|
|
+ EntityModifyEvent::new);
|
|
|
+ }
|
|
|
+ return Mono.empty();
|
|
|
+ });
|
|
|
});
|
|
|
- });
|
|
|
-
|
|
|
- holder.before(
|
|
|
- ((ReactiveRepository<Object, ?>) repo)
|
|
|
- .createQuery()
|
|
|
- .setParam(update.toQueryParam())
|
|
|
- .fetch()
|
|
|
- .collectList()
|
|
|
- .flatMap((list) -> {
|
|
|
- List<Object> after = createAfterData(list, context);
|
|
|
- updated.set(Tuples.of(list, after));
|
|
|
- return sendUpdateEvent(list,
|
|
|
- after,
|
|
|
- (Class) mapping.getEntityType(),
|
|
|
- EntityBeforeModifyEvent::new);
|
|
|
-
|
|
|
- })
|
|
|
- .then()
|
|
|
- );
|
|
|
+ }
|
|
|
+
|
|
|
});
|
|
|
} else if (repo instanceof SyncRepository) {
|
|
|
- QueryParam param = update.toQueryParam();
|
|
|
- SyncRepository<Object, ?> syncRepository = ((SyncRepository<Object, ?>) repo);
|
|
|
- List<Object> list = syncRepository.createQuery()
|
|
|
- .setParam(param)
|
|
|
- .fetch();
|
|
|
- sendUpdateEvent(list,
|
|
|
- createAfterData(list, context),
|
|
|
- (Class<Object>) mapping.getEntityType(),
|
|
|
- EntityBeforeModifyEvent::new).block();
|
|
|
+ if (isEnabled(entityType, EntityEventType.modify, EntityEventPhase.before)) {
|
|
|
+ QueryParam param = update.toQueryParam();
|
|
|
+ SyncRepository<Object, ?> syncRepository = ((SyncRepository<Object, ?>) repo);
|
|
|
+ List<Object> list = syncRepository.createQuery()
|
|
|
+ .setParam(param)
|
|
|
+ .fetch();
|
|
|
+ sendUpdateEvent(list,
|
|
|
+ createAfterData(list, context),
|
|
|
+ (Class<Object>) mapping.getEntityType(),
|
|
|
+ EntityBeforeModifyEvent::new)
|
|
|
+ .block();
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -218,7 +276,7 @@ public class EntityEventListener implements EventListener {
|
|
|
|
|
|
}
|
|
|
|
|
|
- protected void handleDeleteBefore(EventContext context) {
|
|
|
+ protected void handleDeleteBefore(Class<Entity> entityType, EventContext context) {
|
|
|
EntityColumnMapping mapping = context
|
|
|
.get(MappingContextKeys.columnMapping)
|
|
|
.orElseThrow(UnsupportedOperationException::new);
|
|
@@ -229,28 +287,33 @@ public class EntityEventListener implements EventListener {
|
|
|
context.get(MappingContextKeys.reactiveResultHolder)
|
|
|
.ifPresent(holder -> {
|
|
|
AtomicReference<List<Object>> deleted = new AtomicReference<>();
|
|
|
- holder.after(v -> {
|
|
|
- return Mono
|
|
|
- .defer(() -> {
|
|
|
- List<Object> _tmp = deleted.getAndSet(null);
|
|
|
- if (CollectionUtils.isNotEmpty(_tmp)) {
|
|
|
- return sendDeleteEvent(_tmp, (Class) mapping.getEntityType(), EntityDeletedEvent::new);
|
|
|
- }
|
|
|
- return Mono.empty();
|
|
|
- });
|
|
|
- });
|
|
|
- holder.before(((ReactiveRepository<Object, ?>) repo)
|
|
|
- .createQuery()
|
|
|
- .setParam(dslUpdate.toQueryParam())
|
|
|
- .fetch()
|
|
|
- .collectList()
|
|
|
- .filter(CollectionUtils::isNotEmpty)
|
|
|
- .flatMap(list -> {
|
|
|
- deleted.set(list);
|
|
|
- return this
|
|
|
- .sendDeleteEvent(list, (Class) mapping.getEntityType(), EntityBeforeDeleteEvent::new);
|
|
|
- })
|
|
|
- );
|
|
|
+ if (isEnabled(entityType, EntityEventType.delete, EntityEventPhase.before, EntityEventPhase.after)) {
|
|
|
+ holder.before(((ReactiveRepository<Object, ?>) repo)
|
|
|
+ .createQuery()
|
|
|
+ .setParam(dslUpdate.toQueryParam())
|
|
|
+ .fetch()
|
|
|
+ .collectList()
|
|
|
+ .filter(CollectionUtils::isNotEmpty)
|
|
|
+ .flatMap(list -> {
|
|
|
+ deleted.set(list);
|
|
|
+ return this
|
|
|
+ .sendDeleteEvent(list, (Class) mapping.getEntityType(), EntityBeforeDeleteEvent::new);
|
|
|
+ })
|
|
|
+ );
|
|
|
+ }
|
|
|
+ if (isEnabled(entityType, EntityEventType.delete, EntityEventPhase.after)) {
|
|
|
+ holder.after(v -> {
|
|
|
+ return Mono
|
|
|
+ .defer(() -> {
|
|
|
+ List<Object> _tmp = deleted.getAndSet(null);
|
|
|
+ if (CollectionUtils.isNotEmpty(_tmp)) {
|
|
|
+ return sendDeleteEvent(_tmp, (Class) mapping.getEntityType(), EntityDeletedEvent::new);
|
|
|
+ }
|
|
|
+ return Mono.empty();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
});
|
|
|
} else if (repo instanceof SyncRepository) {
|
|
|
QueryParam param = dslUpdate.toQueryParam();
|
|
@@ -268,29 +331,41 @@ public class EntityEventListener implements EventListener {
|
|
|
|
|
|
}
|
|
|
|
|
|
- protected void handleBatchOperation(Class clazz, EventContext context,
|
|
|
+ protected void handleBatchOperation(Class clazz,
|
|
|
+ EntityEventType entityEventType,
|
|
|
+ EventContext context,
|
|
|
BiFunction<List<?>, Class, AsyncEvent> before,
|
|
|
+ BiFunction<List<?>, Class, AsyncEvent> execute,
|
|
|
BiFunction<List<?>, Class, AsyncEvent> after) {
|
|
|
|
|
|
context.get(MappingContextKeys.instance)
|
|
|
.filter(List.class::isInstance)
|
|
|
.map(List.class::cast)
|
|
|
.ifPresent(lst -> {
|
|
|
+ AsyncEvent prepareEvent = before.apply(lst, clazz);
|
|
|
AsyncEvent afterEvent = after.apply(lst, clazz);
|
|
|
- AsyncEvent beforeEvent = before.apply(lst, clazz);
|
|
|
+ AsyncEvent beforeEvent = execute.apply(lst, clazz);
|
|
|
Object repo = context.get(MappingContextKeys.repository).orElse(null);
|
|
|
if (repo instanceof ReactiveRepository) {
|
|
|
Optional<ReactiveResultHolder> resultHolder = context.get(MappingContextKeys.reactiveResultHolder);
|
|
|
if (resultHolder.isPresent()) {
|
|
|
- eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, beforeEvent, clazz));
|
|
|
ReactiveResultHolder holder = resultHolder.get();
|
|
|
- if (null != beforeEvent) {
|
|
|
- holder.before(beforeEvent.publish(eventPublisher));
|
|
|
+ if (null != prepareEvent && isEnabled(clazz, entityEventType, EntityEventPhase.prepare)) {
|
|
|
+ eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, prepareEvent, clazz));
|
|
|
+ holder.before(prepareEvent.getAsync());
|
|
|
+ }
|
|
|
+ if (null != beforeEvent && isEnabled(clazz, entityEventType, EntityEventPhase.before)) {
|
|
|
+ holder.invoke(Mono.defer(() -> {
|
|
|
+ eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, beforeEvent, clazz));
|
|
|
+ return beforeEvent.getAsync();
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ if (null != afterEvent && isEnabled(clazz, entityEventType, EntityEventPhase.after)) {
|
|
|
+ holder.after(v -> {
|
|
|
+ eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, afterEvent, clazz));
|
|
|
+ return afterEvent.getAsync();
|
|
|
+ });
|
|
|
}
|
|
|
- holder.after(v -> {
|
|
|
- eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, afterEvent, clazz));
|
|
|
- return afterEvent.getAsync();
|
|
|
- });
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
@@ -300,29 +375,50 @@ public class EntityEventListener implements EventListener {
|
|
|
});
|
|
|
}
|
|
|
|
|
|
+ boolean isEnabled(Class clazz, EntityEventType entityEventType, EntityEventPhase... phase) {
|
|
|
+ for (EntityEventPhase entityEventPhase : phase) {
|
|
|
+ if (listenerConfigure.isEnabled(clazz, entityEventType, entityEventPhase)) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
protected void handleSingleOperation(Class clazz,
|
|
|
+ EntityEventType entityEventType,
|
|
|
EventContext context,
|
|
|
BiFunction<List<?>, Class, AsyncEvent> before,
|
|
|
+ BiFunction<List<?>, Class, AsyncEvent> execute,
|
|
|
BiFunction<List<?>, Class, AsyncEvent> after) {
|
|
|
context.get(MappingContextKeys.instance)
|
|
|
.filter(Entity.class::isInstance)
|
|
|
.map(Entity.class::cast)
|
|
|
.ifPresent(entity -> {
|
|
|
+ AsyncEvent prepareEvent = before.apply(Collections.singletonList(entity), clazz);
|
|
|
+ AsyncEvent beforeEvent = execute.apply(Collections.singletonList(entity), clazz);
|
|
|
AsyncEvent afterEvent = after.apply(Collections.singletonList(entity), clazz);
|
|
|
- AsyncEvent beforeEvent = before.apply(Collections.singletonList(entity), clazz);
|
|
|
+
|
|
|
Object repo = context.get(MappingContextKeys.repository).orElse(null);
|
|
|
if (repo instanceof ReactiveRepository) {
|
|
|
Optional<ReactiveResultHolder> resultHolder = context.get(MappingContextKeys.reactiveResultHolder);
|
|
|
if (resultHolder.isPresent()) {
|
|
|
- eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, beforeEvent, clazz));
|
|
|
ReactiveResultHolder holder = resultHolder.get();
|
|
|
- if (null != beforeEvent) {
|
|
|
- holder.before(beforeEvent.publish(eventPublisher));
|
|
|
+ if (null != prepareEvent && isEnabled(clazz, entityEventType, EntityEventPhase.prepare)) {
|
|
|
+ eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, prepareEvent, clazz));
|
|
|
+ holder.before(prepareEvent.getAsync());
|
|
|
+ }
|
|
|
+ if (null != beforeEvent && isEnabled(clazz, entityEventType, EntityEventPhase.before)) {
|
|
|
+ holder.invoke(Mono.defer(() -> {
|
|
|
+ eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, beforeEvent, clazz));
|
|
|
+ return beforeEvent.getAsync();
|
|
|
+ }));
|
|
|
+ }
|
|
|
+ if (null != afterEvent && isEnabled(clazz, entityEventType, EntityEventPhase.after)) {
|
|
|
+ holder.after(v -> {
|
|
|
+ eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, afterEvent, clazz));
|
|
|
+ return afterEvent.getAsync();
|
|
|
+ });
|
|
|
}
|
|
|
- holder.after(v -> {
|
|
|
- eventPublisher.publishEvent(new GenericsPayloadApplicationEvent<>(this, afterEvent, clazz));
|
|
|
- return afterEvent.getAsync();
|
|
|
- });
|
|
|
return;
|
|
|
}
|
|
|
}
|