From 789c5918f45c2178758853d7453b0a1ef84a8dc2 Mon Sep 17 00:00:00 2001
From: Daniel Gerhardt <code@dgerhardt.net>
Date: Mon, 19 Nov 2018 15:40:34 +0100
Subject: [PATCH] Improve StateEventDispatcher's AfterPatchEvent handling

Patching of child objects is now handled.
---
 .../de/thm/arsnova/event/AfterPatchEvent.java | 10 ++++++-
 .../thm/arsnova/event/BeforePatchEvent.java   | 10 ++++++-
 .../arsnova/event/StateEventDispatcher.java   | 26 +++++++++++--------
 .../service/DefaultEntityServiceImpl.java     |  6 ++---
 4 files changed, 36 insertions(+), 16 deletions(-)

diff --git a/src/main/java/de/thm/arsnova/event/AfterPatchEvent.java b/src/main/java/de/thm/arsnova/event/AfterPatchEvent.java
index 847bca9e9..7846644fb 100644
--- a/src/main/java/de/thm/arsnova/event/AfterPatchEvent.java
+++ b/src/main/java/de/thm/arsnova/event/AfterPatchEvent.java
@@ -3,15 +3,23 @@ package de.thm.arsnova.event;
 import de.thm.arsnova.model.Entity;
 
 import java.util.Map;
+import java.util.function.Function;
 
 public class AfterPatchEvent<E extends Entity> extends AfterUpdateEvent<E> {
+	private final Function<E, ? extends Object> propertyGetter;
 	private final Map<String, Object> changes;
 
-	public AfterPatchEvent(final Object source, final E entity, final Map<String, Object> changes) {
+	public AfterPatchEvent(final Object source, final E entity, final Function<E, ? extends Object> propertyGetter,
+			final Map<String, Object> changes) {
 		super(source, entity);
+		this.propertyGetter = propertyGetter;
 		this.changes = changes;
 	}
 
+	public Function<E, ? extends Object> getPropertyGetter() {
+		return propertyGetter;
+	}
+
 	public Map<String, Object> getChanges() {
 		return changes;
 	}
diff --git a/src/main/java/de/thm/arsnova/event/BeforePatchEvent.java b/src/main/java/de/thm/arsnova/event/BeforePatchEvent.java
index 717d14f98..d6ff6d5ca 100644
--- a/src/main/java/de/thm/arsnova/event/BeforePatchEvent.java
+++ b/src/main/java/de/thm/arsnova/event/BeforePatchEvent.java
@@ -3,15 +3,23 @@ package de.thm.arsnova.event;
 import de.thm.arsnova.model.Entity;
 
 import java.util.Map;
+import java.util.function.Function;
 
 public class BeforePatchEvent<E extends Entity> extends BeforeUpdateEvent<E> {
+	private final Function<E, ? extends Object> propertyGetter;
 	private final Map<String, Object> changes;
 
-	public BeforePatchEvent(final Object source, final E entity, final Map<String, Object> changes) {
+	public BeforePatchEvent(final Object source, final E entity, final Function<E, ? extends Object> propertyGetter,
+			final Map<String, Object> changes) {
 		super(source, entity);
+		this.propertyGetter = propertyGetter;
 		this.changes = changes;
 	}
 
+	public Function<E, ? extends Object> getPropertyGetter() {
+		return propertyGetter;
+	}
+
 	public Map<String, Object> getChanges() {
 		return changes;
 	}
diff --git a/src/main/java/de/thm/arsnova/event/StateEventDispatcher.java b/src/main/java/de/thm/arsnova/event/StateEventDispatcher.java
index 7d4993ad6..e887aac52 100644
--- a/src/main/java/de/thm/arsnova/event/StateEventDispatcher.java
+++ b/src/main/java/de/thm/arsnova/event/StateEventDispatcher.java
@@ -31,24 +31,24 @@ public class StateEventDispatcher implements ApplicationEventPublisherAware {
 
 	@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");
+		publishEventIfPropertyChanged(event, Function.identity(), "closed", "closed");
+		publishEventIfPropertyChanged(event, Function.identity(), "settings", "settings");
+		publishEventIfPropertyChanged(event, Room::getSettings, null, "settings");
 	}
 
 	@EventListener
 	public void dispatchContentStateEvent(final AfterFullUpdateEvent<Content> event) {
 		final Content newContent = event.getEntity();
 		final Content oldContent = event.getOldEntity();
+		Function<Content, Content.State> f = Content::getState;
+		f.apply(newContent);
 		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");
+		publishEventIfPropertyChanged(event, Function.identity(), "state", "state");
+		publishEventIfPropertyChanged(event, Content::getState, null, "state");
 	}
 
 	private <E extends Entity, T extends Object> void publishEventIfPropertyChanged(
@@ -60,11 +60,15 @@ public class StateEventDispatcher implements ApplicationEventPublisherAware {
 		}
 	}
 
-	private <E extends Entity> void publishEventIfPropertyChanged(
-			final E entity, final Map<String, Object> changes, final String property, final String stateName) {
-		if (changes.containsKey(property)) {
+	private <E extends Entity, T extends Object> void publishEventIfPropertyChanged(
+			final AfterPatchEvent<E> event, final Function<E, T> propertyGetter, final String property, final String stateName) {
+		final E entity = event.getEntity();
+		final Map<String, Object> changes = event.getChanges();
+		if (event.getPropertyGetter().apply(entity) == propertyGetter.apply(entity)
+				&& (property == null || changes.containsKey(property))) {
+			final Object value = property == null ? event.getPropertyGetter().apply(entity) : changes.get(property);
 			eventPublisher.publishEvent(
-					new StateChangeEvent<>(this, entity, stateName, changes.get(property), null));
+					new StateChangeEvent<>(this, entity, stateName, value, null));
 		}
 	}
 
diff --git a/src/main/java/de/thm/arsnova/service/DefaultEntityServiceImpl.java b/src/main/java/de/thm/arsnova/service/DefaultEntityServiceImpl.java
index 114c0be10..9e9f9b24c 100644
--- a/src/main/java/de/thm/arsnova/service/DefaultEntityServiceImpl.java
+++ b/src/main/java/de/thm/arsnova/service/DefaultEntityServiceImpl.java
@@ -171,9 +171,9 @@ public class DefaultEntityServiceImpl<T extends Entity> implements EntityService
 		reader.readValue(tree);
 		entity.setUpdateTimestamp(new Date());
 		preparePatch(entity);
-		eventPublisher.publishEvent(new BeforePatchEvent<>(this, entity, changes));
+		eventPublisher.publishEvent(new BeforePatchEvent<>(this, entity, propertyGetter, changes));
 		final T patchedEntity = repository.save(entity);
-		eventPublisher.publishEvent(new AfterPatchEvent<>(this, patchedEntity, changes));
+		eventPublisher.publishEvent(new AfterPatchEvent<>(this, patchedEntity, propertyGetter, changes));
 
 		return patchedEntity;
 	}
@@ -194,7 +194,7 @@ public class DefaultEntityServiceImpl<T extends Entity> implements EntityService
 			reader.readValue(tree);
 			entity.setUpdateTimestamp(new Date());
 			preparePatch(entity);
-			eventPublisher.publishEvent(new BeforePatchEvent<>(this, entity, changes));
+			eventPublisher.publishEvent(new BeforePatchEvent<>(this, entity, propertyGetter, changes));
 		}
 
 		return repository.saveAll(entities);
-- 
GitLab