package org.swellrt.beta.model.remote; import org.swellrt.beta.model.SEvent; import org.swellrt.beta.model.SHandler; import org.swellrt.beta.model.SObservable; import org.waveprotocol.wave.model.util.CopyOnWriteSet; import jsinterop.annotations.JsIgnore; import jsinterop.annotations.JsType; @JsType(namespace = "swellrt", name = "ListenableNode") public abstract class SNodeRemoteContainer extends SNodeRemote implements SObservable { @JsIgnore public static SNodeRemoteContainer Void = new SNodeRemoteContainer() { @Override protected void clearCache() { // Nothing to do } }; protected boolean eventsEnabled = false; private final CopyOnWriteSet<SHandler> eventHandlerSet = CopyOnWriteSet.<SHandler>createHashSet(); protected SNodeRemoteContainer() { super(null, null); } protected SNodeRemoteContainer(SubstrateId substrateId, SObjectRemote object) { super(substrateId, object); } @Override protected void attach(SNodeRemoteContainer parent) { super.attach(parent); this.eventHandlerSet.clear(); this.eventsEnabled = true; } @Override protected void deattach() { this.eventsEnabled = false; this.eventHandlerSet.clear(); super.deattach(); } /** * Cleans the local cache recursively to mock * remote behavior in tests. */ protected abstract void clearCache(); @Override public void listen(SHandler h) { eventHandlerSet.add(h); } @Override public void unlisten(SHandler h) { eventHandlerSet.remove(h); } protected void triggerEvent(SEvent e) { if (!this.eventsEnabled) return; boolean propagate = true; for (SHandler h: eventHandlerSet) { propagate = propagate && h.exec(e); } if (propagate && this.getParent() != null && !this.getParent().equals(Void)) { this.getParent().triggerEvent(e); } } /** * Only For testing. Disable any event generation nor propagation * from this node upwards. * @param enabled */ protected void enableEvents(boolean enabled) { this.eventsEnabled = enabled; if (this.getParent() != null && !this.getParent().equals(Void)) this.getParent().enableEvents(enabled); } }