package org.infinispan.functional.impl; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Supplier; import org.infinispan.commons.api.functional.EntryView.ReadEntryView; import org.infinispan.commons.util.Experimental; /** * @since 8.0 */ @Experimental public final class FunctionalNotifierImpl<K, V> implements FunctionalNotifier<K, V> { final List<Consumer<ReadEntryView<K, V>>> onCreates = new CopyOnWriteArrayList<>(); final List<BiConsumer<ReadEntryView<K, V>, ReadEntryView<K, V>>> onModifies = new CopyOnWriteArrayList<>(); final List<Consumer<ReadEntryView<K, V>>> onRemoves = new CopyOnWriteArrayList<>(); final List<Consumer<ReadEntryView<K, V>>> onWrites = new CopyOnWriteArrayList<>(); final List<ReadWriteListener<K, V>> rwListeners = new CopyOnWriteArrayList<>(); final List<WriteListener<K, V>> writeListeners = new CopyOnWriteArrayList<>(); @Override public AutoCloseable add(WriteListener<K, V> l) { writeListeners.add(l); return new ListenerCloseable<>(l, writeListeners); } @Override public AutoCloseable add(ReadWriteListener<K, V> l) { rwListeners.add(l); return new ListenerCloseable<>(l, rwListeners); } @Override public AutoCloseable onCreate(Consumer<ReadEntryView<K, V>> f) { onCreates.add(f); return new ListenerCloseable<>(f, onCreates); } @Override public AutoCloseable onModify(BiConsumer<ReadEntryView<K, V>, ReadEntryView<K, V>> f) { onModifies.add(f); return new ListenerCloseable<>(f, onModifies); } @Override public AutoCloseable onRemove(Consumer<ReadEntryView<K, V>> f) { onRemoves.add(f); return new ListenerCloseable<>(f, onRemoves); } @Override public AutoCloseable onWrite(Consumer<ReadEntryView<K, V>> f) { onWrites.add(f); return new ListenerCloseable<>(f, onWrites); } @Override public void notifyOnCreate(ReadEntryView<K, V> created) { onCreates.forEach(c -> c.accept(created)); rwListeners.forEach(rwl -> rwl.onCreate(created)); } @Override public void notifyOnModify(ReadEntryView<K, V> before, ReadEntryView<K, V> after) { onModifies.forEach(c -> c.accept(before, after)); rwListeners.forEach(rwl -> rwl.onModify(before, after)); } @Override public void notifyOnRemove(ReadEntryView<K, V> removed) { onRemoves.forEach(c -> c.accept(removed)); rwListeners.forEach(rwl -> rwl.onRemove(removed)); } @Override public void notifyOnWrite(Supplier<ReadEntryView<K, V>> write) { if (!onWrites.isEmpty()) onWrites.forEach(c -> c.accept(write.get())); if (!writeListeners.isEmpty()) writeListeners.forEach(wl -> wl.onWrite(write.get())); } private static final class ListenerCloseable<T> implements AutoCloseable { final T f; final List<T> list; private ListenerCloseable(T f, List<T> list) { this.f = f; this.list = list; } @Override public void close() throws Exception { list.remove(f); } } }