From d34c316407ec88349ef198497b61bbc7a9b495ff Mon Sep 17 00:00:00 2001 From: Daniel Gerhardt <code@dgerhardt.net> Date: Mon, 12 Nov 2018 15:38:37 +0100 Subject: [PATCH] Add StateChangeEvent for state changes of entities --- .../thm/arsnova/event/StateChangeEvent.java | 45 +++++++++++ .../arsnova/event/StateEventDispatcher.java | 75 +++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 src/main/java/de/thm/arsnova/event/StateChangeEvent.java create mode 100644 src/main/java/de/thm/arsnova/event/StateEventDispatcher.java diff --git a/src/main/java/de/thm/arsnova/event/StateChangeEvent.java b/src/main/java/de/thm/arsnova/event/StateChangeEvent.java new file mode 100644 index 000000000..69b557981 --- /dev/null +++ b/src/main/java/de/thm/arsnova/event/StateChangeEvent.java @@ -0,0 +1,45 @@ +package de.thm.arsnova.event; + +import de.thm.arsnova.model.Entity; +import org.springframework.context.ApplicationEvent; +import org.springframework.core.ResolvableType; +import org.springframework.core.ResolvableTypeProvider; + +import java.util.Optional; + +public class StateChangeEvent<E extends Entity, T> extends ApplicationEvent implements ResolvableTypeProvider { + private final E entity; + private final String stateName; + private final T newValue; + private final T oldValue; + + public StateChangeEvent(final Object source, final E entity, final String stateName, + final T newValue, final T oldValue) { + super(source); + this.entity = entity; + this.stateName = stateName; + this.newValue = newValue; + this.oldValue = oldValue; + } + + public E getEntity() { + return entity; + } + + public String getStateName() { + return stateName; + } + + public T getNewValue() { + return newValue; + } + + public Optional<T> getOldValue() { + return Optional.ofNullable(oldValue); + } + + @Override + public ResolvableType getResolvableType() { + return ResolvableType.forClassWithGenerics(getClass(), entity.getClass(), newValue.getClass()); + } +} diff --git a/src/main/java/de/thm/arsnova/event/StateEventDispatcher.java b/src/main/java/de/thm/arsnova/event/StateEventDispatcher.java new file mode 100644 index 000000000..7d4993ad6 --- /dev/null +++ b/src/main/java/de/thm/arsnova/event/StateEventDispatcher.java @@ -0,0 +1,75 @@ +package de.thm.arsnova.event; + +import de.thm.arsnova.model.Content; +import de.thm.arsnova.model.Entity; +import de.thm.arsnova.model.Room; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.ApplicationEventPublisherAware; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.function.Function; + +/** + * StateEventDispatcher publishes additional, more specific events for state changes of entities when + * {@link AfterUpdateEvent}s are received. + * + * @author Daniel Gerhardt + */ +@Component +public class StateEventDispatcher implements ApplicationEventPublisherAware { + private ApplicationEventPublisher eventPublisher; + + @EventListener + public void dispatchRoomStateEvent(final AfterFullUpdateEvent<Room> event) { + final Room newRoom = event.getEntity(); + final Room oldRoom = event.getOldEntity(); + publishEventIfPropertyChanged(newRoom, oldRoom, Room::isClosed, "closed"); + publishEventIfPropertyChanged(newRoom, oldRoom, Room::getSettings, "settings"); + } + + @EventListener + public void dispatchRoomStateEvent(final AfterPatchEvent<Room> event) { + final Room room = event.getEntity(); + final Map<String, Object> changes = event.getChanges(); + publishEventIfPropertyChanged(room, changes, "closed", "closed"); + publishEventIfPropertyChanged(room, changes, "settings", "settings"); + } + + @EventListener + public void dispatchContentStateEvent(final AfterFullUpdateEvent<Content> event) { + final Content newContent = event.getEntity(); + final Content oldContent = event.getOldEntity(); + publishEventIfPropertyChanged(newContent, oldContent, Content::getState, "state"); + } + + @EventListener + public void dispatchContentStateEvent(final AfterPatchEvent<Content> event) { + final Content content = event.getEntity(); + final Map<String, Object> changes = event.getChanges(); + publishEventIfPropertyChanged(content, changes, "state", "state"); + } + + private <E extends Entity, T extends Object> void publishEventIfPropertyChanged( + final E newEntity, final E oldEntity, final Function<E, T> propertyGetter, final String stateName) { + T newValue = propertyGetter.apply(newEntity); + T oldValue = propertyGetter.apply(oldEntity); + if (!newValue.equals(oldValue)) { + eventPublisher.publishEvent(new StateChangeEvent<>(this, newEntity, stateName, newValue, oldValue)); + } + } + + private <E extends Entity> void publishEventIfPropertyChanged( + final E entity, final Map<String, Object> changes, final String property, final String stateName) { + if (changes.containsKey(property)) { + eventPublisher.publishEvent( + new StateChangeEvent<>(this, entity, stateName, changes.get(property), null)); + } + } + + @Override + public void setApplicationEventPublisher(final ApplicationEventPublisher applicationEventPublisher) { + this.eventPublisher = applicationEventPublisher; + } +} -- GitLab