|
|
@@ -11,6 +11,12 @@ import lombok.AllArgsConstructor;
|
|
|
import lombok.experimental.FieldDefaults;
|
|
|
import lombok.experimental.UtilityClass;
|
|
|
|
|
|
+/**
|
|
|
+ * The master object that associates observale objects with listeners and invocations
|
|
|
+ * TODO: May crash if updating an object where a Listener was destroyed without unsub
|
|
|
+ * TODO: Potentially leaks memory if Listeners go out of scope without unsub
|
|
|
+ * TODO: No way to drop Observable objects as they go out of scope
|
|
|
+ */
|
|
|
@UtilityClass
|
|
|
@FieldDefaults(level=AccessLevel.PRIVATE, makeFinal=true)
|
|
|
public class ObserverDispatch {
|
|
|
@@ -23,20 +29,44 @@ public class ObserverDispatch {
|
|
|
|
|
|
Multimap<UUID, Pair> observers = LinkedListMultimap.create();
|
|
|
|
|
|
+ /**
|
|
|
+ * Register a listener callback
|
|
|
+ * @param target The object we're observing. Make sure that it's an observable and not just
|
|
|
+ * some random UUID someone came up with to harass me.
|
|
|
+ * @param src The Listener object that we are using, used for invalidation in case we
|
|
|
+ * forget to invoke {@see unsubscribeAll} when destroying an object.
|
|
|
+ * @param sub A callback function with a signature of void() that will be triggered when
|
|
|
+ * we request an update.
|
|
|
+ */
|
|
|
public void subscribe(Observable target, Object src, Subscriber sub) {
|
|
|
observers.put(target.observableId(), new Pair(new WeakReference<>(src), sub));
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Remove every callback that this listener is associated with
|
|
|
+ * @param src A Listener object that was generally provided in a previous {@see subscribe}
|
|
|
+ * call.
|
|
|
+ */
|
|
|
public void unsubscribeAll(Object src) {
|
|
|
if (src == null) return;
|
|
|
observers.entries().removeIf( e -> e.getValue().obj.get() == src );
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Dispatch notices of an update to an observable object that comes from an owning
|
|
|
+ * {@see IndirectObservableListener}.
|
|
|
+ * @param target The Observable that was updated by our caller
|
|
|
+ * @param src An owning Listener that does not need to be updated.
|
|
|
+ */
|
|
|
void notifySubscribers(Observable target, IndirectObservableListener<?, ?> src) {
|
|
|
observers.get(target.observableId()).stream().filter(
|
|
|
p -> p.obj.get() != src).forEach( p -> p.sub.notifyUpdate() );
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * Dispatch notices of an update to an observable object.
|
|
|
+ * @param target The Observable that was updated by our caller
|
|
|
+ */
|
|
|
public void notifySubscribers(Observable target) {
|
|
|
observers.get(target.observableId()).stream().forEach( p -> p.sub.notifyUpdate() );
|
|
|
}
|