package eu.dnetlib.enabling.resultset; import java.util.Map; import java.util.WeakHashMap; import eu.dnetlib.enabling.resultset.observer.DelegationObserver; import eu.dnetlib.enabling.resultset.observer.Observable; /** * Common stuff for resultset implementations bound to a ResultSetRegistry. * * @author marko * */ public abstract class AbstractObservableResultset implements ResultSet, Observable { /** * true if the resultset is destroyed. */ private boolean destroyed = false; /** * true if the resultset is open. */ private boolean open; /** * delegate the real job to a java.util.Observable object. */ private transient final java.util.Observable observable = new DelegationObservable(); /** * weak map for removing single observers later on. */ private transient Map observers = new WeakHashMap(); /** * java.util.Observable requires a "change" in the object to be made for the notifyObservers methods to trigger * actually the notification. We don't think this should be part of the base Observable/Observer pattern and thus * hide this fact. If an user of AbstractObservable wants this behavior it should implement her own change tracking * and avoid calling notifyObservers altogether. The rationale behind this choice is that not all dirty states can * be expressed using a stateful boolean instance variable like that implemented by java.util.Observable; some users * may prefer/need a lazy dirty flag instead. * * @author marko * */ static class DelegationObservable extends java.util.Observable { /** * {@inheritDoc} * * @see java.util.Observable#notifyObservers() */ @Override public void notifyObservers() { setChanged(); super.notifyObservers(); } /** * {@inheritDoc} * * @see java.util.Observable#notifyObservers(java.lang.Object) */ @Override public void notifyObservers(final Object arg) { setChanged(); super.notifyObservers(arg); } } /** * {@inheritDoc} * * @see eu.dnetlib.enabling.resultset.ResultSet#destroy() */ @Override public void destroy() { if (!isDestroyed()) { setDestroyed(true); notifyObservers(); deleteObservers(); } } public void setDestroyed(final boolean destroyed) { this.destroyed = destroyed; } @Override public boolean isDestroyed() { return destroyed; } /** * {@inheritDoc} * * @see eu.dnetlib.enabling.resultset.ResultSet#isOpen() */ @Override public boolean isOpen() { return open; } /** * {@inheritDoc} * * @see eu.dnetlib.enabling.resultset.ResultSet#close() */ @Override public void close() { open = false; } public void setOpen(final boolean open) { this.open = open; } @Override public void addObserver(final ResultSetRegistry observer) { final DelegationObserver delegate = new DelegationObserver(this, observer); observers.put(observer, delegate); observable.addObserver(delegate); } protected void notifyObservers() { observable.notifyObservers(); } protected void notifyObservers(final Object arg) { observable.notifyObservers(arg); } public int countObservers() { return observable.countObservers(); } public void deleteObserver(final java.util.Observer observer) { observable.deleteObserver(observer); } public void deleteObserver(ResultSetRegistry observer) { DelegationObserver delegate = observers.get(observer); if(delegate != null) { observable.deleteObserver(delegate); } } public void deleteObservers() { observable.deleteObservers(); } }