summaryrefslogtreecommitdiff
path: root/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationCenter.java
diff options
context:
space:
mode:
authorBenjamin Culkin <scorpress@gmail.com>2024-05-20 17:58:16 -0400
committerBenjamin Culkin <scorpress@gmail.com>2024-05-20 17:58:16 -0400
commit40a9d99496e098562f090fb7ffce9e749011b131 (patch)
tree437df24d65470582e943e494a52db8ed65a881ae /projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationCenter.java
parentff072dfe782f6f22123cd4ba050828d35c0d0fbd (diff)
Formatting pass
Diffstat (limited to 'projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationCenter.java')
-rw-r--r--projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationCenter.java1086
1 files changed, 473 insertions, 613 deletions
diff --git a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationCenter.java b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationCenter.java
index aaf8261..cf0af53 100644
--- a/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationCenter.java
+++ b/projects/net.wotonomy.foundation/src/main/java/net/wotonomy/foundation/NSNotificationCenter.java
@@ -30,642 +30,502 @@ import java.util.Vector;
import net.wotonomy.foundation.internal.WotonomyException;
/**
-* NSNotificationCenter broadcasts NSNotifications to
-* registered observers. Observers can register for all
-* notifications of a specific type, or all notifications
-* about a specific object, or both. Observers specify
-* the method that will be called when they are notified.
-* A global notification center can be accessed with
-* defaultCenter(), but other centers can be created and
-* used independently of the default center. <br><br>
-*
-* This implementation uses weak references for observers
-* and observables. The advantage to this approach is
-* that you do not need to explicitly unregister observers
-* or observables; they will be unregistered when they are
-* garbage-collected. Note that you will need to retain
-* a reference to any objects you register or they may
-* become unregistered if no other object references them.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 893 $
-*/
-public class NSNotificationCenter
-{
- /**
- * Null marker class simplifies equals() logic
- * for CompoundKey class below.
- */
- public static final Object NullMarker = new Object();
-
- private static NSNotificationCenter defaultCenter = null;
-
- /**
- * A Map of (name,object) pairs to a List
- * of (observer,selector) pairs.
- */
- private Hashtable observers; // thread-safe
-
- /**
- * Default constructor creates a new notification center.
- */
- public NSNotificationCenter()
- {
- observers = new Hashtable();
- }
-
- /**
- * Returns the system default center, creating one
- * if it has not yet been created.
- */
- static public NSNotificationCenter defaultCenter()
- {
- if ( defaultCenter == null )
- {
- defaultCenter = new NSNotificationCenter();
- }
- return defaultCenter;
- }
-
+ * NSNotificationCenter broadcasts NSNotifications to registered observers.
+ * Observers can register for all notifications of a specific type, or all
+ * notifications about a specific object, or both. Observers specify the method
+ * that will be called when they are notified. A global notification center can
+ * be accessed with defaultCenter(), but other centers can be created and used
+ * independently of the default center. <br>
+ * <br>
+ *
+ * This implementation uses weak references for observers and observables. The
+ * advantage to this approach is that you do not need to explicitly unregister
+ * observers or observables; they will be unregistered when they are
+ * garbage-collected. Note that you will need to retain a reference to any
+ * objects you register or they may become unregistered if no other object
+ * references them.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 893 $
+ */
+public class NSNotificationCenter {
+ /**
+ * Null marker class simplifies equals() logic for CompoundKey class below.
+ */
+ public static final Object NullMarker = new Object();
+
+ private static NSNotificationCenter defaultCenter = null;
+
/**
- * Addes the specified observer to the notification queue for
- * notifications with the specified name or the specified
- * object or both.
- * @param anObserver The observer that wishes to be notified.
- * @param aSelector The selector that will be invoked.
- * Must have exactly one argument, to which a notification
- * will be passed.
- * @param notificationName The name of the notifications for
- * which the observer will be notified. If null, will notify
- * only based on matching anObject.
- * @param anObject The object of the notifications for which
- * the observer will be notified. If null, will notify
- * only based on matching notificationName.
- */
- public void addObserver(
- Object anObserver, NSSelector aSelector,
- String notificationName, Object anObject )
- {
- // remove freed objects
- processKeyQueue();
-
- Object name = notificationName;
- if ( name == null )
- {
- name = NullMarker;
- }
- if ( anObject == null )
- {
- anObject = NullMarker;
- }
- Object key = new CompoundKey( name, anObject );
- Object value = new CompoundValue( anObserver, aSelector );
- List list = (List) observers.get( key );
- if ( list == null )
- {
- // create new list with value and put it in map
- list = new Vector(); // thread-safe
- list.add( value );
- observers.put( new CompoundKey(
- name, anObject, keyQueue ), list );
- }
- else
- {
- // add only if not already in list
- if ( ! list.contains( value ) )
- {
- list.add( value );
- }
- }
- }
-
+ * A Map of (name,object) pairs to a List of (observer,selector) pairs.
+ */
+ private Hashtable observers; // thread-safe
+
+ /**
+ * Default constructor creates a new notification center.
+ */
+ public NSNotificationCenter() {
+ observers = new Hashtable();
+ }
+
+ /**
+ * Returns the system default center, creating one if it has not yet been
+ * created.
+ */
+ static public NSNotificationCenter defaultCenter() {
+ if (defaultCenter == null) {
+ defaultCenter = new NSNotificationCenter();
+ }
+ return defaultCenter;
+ }
+
+ /**
+ * Addes the specified observer to the notification queue for notifications with
+ * the specified name or the specified object or both.
+ *
+ * @param anObserver The observer that wishes to be notified.
+ * @param aSelector The selector that will be invoked. Must have exactly
+ * one argument, to which a notification will be passed.
+ * @param notificationName The name of the notifications for which the observer
+ * will be notified. If null, will notify only based on
+ * matching anObject.
+ * @param anObject The object of the notifications for which the
+ * observer will be notified. If null, will notify only
+ * based on matching notificationName.
+ */
+ public void addObserver(Object anObserver, NSSelector aSelector, String notificationName, Object anObject) {
+ // remove freed objects
+ processKeyQueue();
+
+ Object name = notificationName;
+ if (name == null) {
+ name = NullMarker;
+ }
+ if (anObject == null) {
+ anObject = NullMarker;
+ }
+ Object key = new CompoundKey(name, anObject);
+ Object value = new CompoundValue(anObserver, aSelector);
+ List list = (List) observers.get(key);
+ if (list == null) {
+ // create new list with value and put it in map
+ list = new Vector(); // thread-safe
+ list.add(value);
+ observers.put(new CompoundKey(name, anObject, keyQueue), list);
+ } else {
+ // add only if not already in list
+ if (!list.contains(value)) {
+ list.add(value);
+ }
+ }
+ }
+
/**
- * Posts the specified notification. Notifies all registered
- * observers that match either the notification name or
- * the notification object, or both.
- * @param aNotification The notification that will be passed
- * to the observers selector.
- */
- public void postNotification(
- NSNotification aNotification )
- {
- List mergedList = new LinkedList();
- Object key, observerList;
-
- Object name = aNotification.name();
- Object object = aNotification.object();
-
- if ( name != null )
- {
- if ( object != null )
- { // both are specified
- observerList = observers.get( new CompoundKey( name, object ) );
- if ( observerList != null )
- {
- mergedList.addAll( (List) observerList );
- }
- observerList = observers.get( new CompoundKey( name, NullMarker ) );
- if ( observerList != null )
- {
- mergedList.addAll( (List) observerList );
- }
- observerList = observers.get( new CompoundKey( NullMarker, object ) );
- if ( observerList != null )
- {
- mergedList.addAll( (List) observerList );
- }
- }
- else
- { // object is null
- observerList = observers.get( new CompoundKey( name, NullMarker ) );
- if ( observerList != null )
- {
- mergedList.addAll( (List) observerList );
- }
- }
- }
- else
- if ( object != null )
- { // name is null
- observerList = observers.get( new CompoundKey( NullMarker, object ) );
- if ( observerList != null )
- {
- mergedList.addAll( (List) observerList );
- }
- }
-
- key = new CompoundKey(
- NullMarker, NullMarker );
- observerList = observers.get( key );
- if ( observerList != null )
- {
- mergedList.addAll( (List) observerList );
- }
-
- CompoundValue value;
- Iterator it = mergedList.iterator();
- while ( it.hasNext() )
- {
- value = (CompoundValue) it.next();
- if ( value.get() == null )
- {
- it.remove();
- }
- else
- {
- try
- {
- value.selector().invoke(
- value.get(),
- new Object[] { aNotification } );
- }
- catch ( Exception exc )
- {
- WotonomyException w = new WotonomyException(
- "Error notifying object: " + value.get() + " : " + aNotification, exc );
+ * Posts the specified notification. Notifies all registered observers that
+ * match either the notification name or the notification object, or both.
+ *
+ * @param aNotification The notification that will be passed to the observers
+ * selector.
+ */
+ public void postNotification(NSNotification aNotification) {
+ List mergedList = new LinkedList();
+ Object key, observerList;
+
+ Object name = aNotification.name();
+ Object object = aNotification.object();
+
+ if (name != null) {
+ if (object != null) { // both are specified
+ observerList = observers.get(new CompoundKey(name, object));
+ if (observerList != null) {
+ mergedList.addAll((List) observerList);
+ }
+ observerList = observers.get(new CompoundKey(name, NullMarker));
+ if (observerList != null) {
+ mergedList.addAll((List) observerList);
+ }
+ observerList = observers.get(new CompoundKey(NullMarker, object));
+ if (observerList != null) {
+ mergedList.addAll((List) observerList);
+ }
+ } else { // object is null
+ observerList = observers.get(new CompoundKey(name, NullMarker));
+ if (observerList != null) {
+ mergedList.addAll((List) observerList);
+ }
+ }
+ } else if (object != null) { // name is null
+ observerList = observers.get(new CompoundKey(NullMarker, object));
+ if (observerList != null) {
+ mergedList.addAll((List) observerList);
+ }
+ }
+
+ key = new CompoundKey(NullMarker, NullMarker);
+ observerList = observers.get(key);
+ if (observerList != null) {
+ mergedList.addAll((List) observerList);
+ }
+
+ CompoundValue value;
+ Iterator it = mergedList.iterator();
+ while (it.hasNext()) {
+ value = (CompoundValue) it.next();
+ if (value.get() == null) {
+ it.remove();
+ } else {
+ try {
+ value.selector().invoke(value.get(), new Object[] { aNotification });
+ } catch (Exception exc) {
+ WotonomyException w = new WotonomyException(
+ "Error notifying object: " + value.get() + " : " + aNotification, exc);
// throw w;
- w.printStackTrace();
-postNotification( "Error notifying object", this, new NSDictionary( "exception", w ) );
- }
- }
- }
-
- }
-
+ w.printStackTrace();
+ postNotification("Error notifying object", this, new NSDictionary("exception", w));
+ }
+ }
+ }
+
+ }
+
/**
- * Posts a notification created from the specified name
- * and object. Calls postNotification( NSNotification ).
- * @param notificationName a String key to distinguish
- * this notification.
- * @param anObject any object, by convention this is
- * the originator of the notification.
- */
- public void postNotification(
- String notificationName, Object anObject )
- {
- postNotification( new NSNotification(
- notificationName, anObject ) );
- }
-
+ * Posts a notification created from the specified name and object. Calls
+ * postNotification( NSNotification ).
+ *
+ * @param notificationName a String key to distinguish this notification.
+ * @param anObject any object, by convention this is the originator of
+ * the notification.
+ */
+ public void postNotification(String notificationName, Object anObject) {
+ postNotification(new NSNotification(notificationName, anObject));
+ }
+
/**
- * Posts a notification created from the specified name,
- * object, and info. Calls postNotification( NSNotification ).
- * @param notificationName a String key to distinguish
- * this notification.
- * @param anObject any object, by convention this is
- * the originator of the notification.
- * @param userInfo a Map containing information specific
- * to the originator of the notification and that may
- * be of interest to a knowledgable observer.
- */
- public void postNotification(
- String notificationName, Object anObject, Map userInfo )
- {
- postNotification( new NSNotification(
- notificationName, anObject, userInfo ) );
- }
-
+ * Posts a notification created from the specified name, object, and info. Calls
+ * postNotification( NSNotification ).
+ *
+ * @param notificationName a String key to distinguish this notification.
+ * @param anObject any object, by convention this is the originator of
+ * the notification.
+ * @param userInfo a Map containing information specific to the
+ * originator of the notification and that may be of
+ * interest to a knowledgable observer.
+ */
+ public void postNotification(String notificationName, Object anObject, Map userInfo) {
+ postNotification(new NSNotification(notificationName, anObject, userInfo));
+ }
+
/**
- * Unregisters the specified observer from all notification
- * queues for which it is registered.
- * @param anObserver The observer to be unregistered.
- */
- public void removeObserver(
- Object anObserver )
- {
- // remove freed objects
- processKeyQueue();
-
- Iterator it = new LinkedList( observers.keySet() ).iterator();
- while ( it.hasNext() )
- {
- removeObserver( anObserver, it.next() );
- }
- }
-
+ * Unregisters the specified observer from all notification queues for which it
+ * is registered.
+ *
+ * @param anObserver The observer to be unregistered.
+ */
+ public void removeObserver(Object anObserver) {
+ // remove freed objects
+ processKeyQueue();
+
+ Iterator it = new LinkedList(observers.keySet()).iterator();
+ while (it.hasNext()) {
+ removeObserver(anObserver, it.next());
+ }
+ }
+
/**
- * Unregisters the specified observer from all notifications
- * queues associated with the specified name or object or both.
- * @param anObserver The observer to be unregistered, if null
- * will unregister all observers for the specified notification
- * name and object.
- * @param notificationName The name of the notification for which
- * the observer will be unregistered, if null will unregister
- * the specified observer for all notifications with the
- * specified object.
- * @param anObject The object for the notification for which
- * the observer will be unregistered, if null will unregister
- * the specified observer for all objects with the specified
- * notification.
- */
- public void removeObserver(
- Object anObserver, String notificationName, Object anObject )
- {
- // remove freed objects
- processKeyQueue();
-
- // get key matches
- List keys = matchingKeys( notificationName, anObject );
-
- // remove specified observer from each matching key
- Iterator it = keys.iterator();
- while ( it.hasNext() )
- {
- removeObserver( anObserver, it.next() );
- }
- }
-
- /**
- * Returns all keys that match the specified name and object,
- * but in this case null parameters are considered wildcards.
- * Pass NullMarkers if you want to explicitly match nulls.
- */
- private List matchingKeys( String name, Object object )
- {
- List result = new LinkedList();
-
- boolean willAdd;
- CompoundKey key;
- Iterator it = observers.keySet().iterator();
- while ( it.hasNext() )
- {
- key = (CompoundKey) it.next();
- willAdd = false;
- if ( ( name == null ) || ( name == key.name() ) )
- {
- if ( ( object == null ) || ( object == key.get() ) )
- {
- willAdd = true;
- }
- }
- if ( willAdd )
- {
- result.add( key );
- }
- }
- return result;
- }
-
- /**
- * Removes the specified observer from the list referenced
- * by the specified key in the observer map.
- */
- private void removeObserver(
- Object anObserver, Object key )
- {
- // if observer null, remove all observers for key
- if ( anObserver == null )
- {
- observers.remove( key );
- return;
- }
-
- List list = (List) observers.get( key );
- if ( list == null ) return;
-
- // remove specified observer from list
- Object observer;
- Iterator it = list.iterator();
- while ( it.hasNext() )
- {
- observer = ((CompoundValue)it.next()).get();
- if ( ( observer == null ) || ( anObserver == observer ) )
- {
- // remove if match or freed object
- it.remove();
-
- // do not return; process entire list
- }
- }
- if ( list.size() == 0 )
- {
- observers.remove( key );
- }
- }
-
- /* Reference queues for cleared WeakKeys */
- private ReferenceQueue keyQueue = new ReferenceQueue();
-
- /**
- * Removes any keys whose object has been garbage collected.
- * (Garbage collected values are removed as they are encountered.)
- */
- private void processKeyQueue()
- {
- CompoundKey ck;
- while ((ck = (CompoundKey)keyQueue.poll()) != null)
- {
- //System.out.println( "EOObserverCenter.processQueue: removing object" );
- observers.remove(ck);
- }
- }
-
- /**
- * Key combining a name with an object.
- * The object is weakly referenced, and keys
- * are deallocated by reference queue.
- * equals() compares by reference.
- */
- private static class CompoundKey extends WeakReference
- {
- private Object name;
- private int hashCode;
-
- /**
- * Creates compound key.
- * Neither name nor object may be null.
- * Use NullMarker to represent null
- * in either name or object.
- */
- public CompoundKey (
- Object aName, Object anObject )
- {
- super( anObject );
- name = aName;
- hashCode = aName.hashCode() + anObject.hashCode();
- }
-
- /**
- * Creates compound key with queue.
- * Neither name nor object may be null.
- * Use NullMarker to represent null
- * in either name or object.
- */
- public CompoundKey (
- Object aName, Object anObject, ReferenceQueue aQueue )
- {
- super( anObject, aQueue );
- name = aName;
- hashCode = aName.hashCode() + anObject.hashCode();
- }
-
- public Object name()
- {
- return name;
- }
-
- public int hashCode()
- {
- return hashCode;
- }
-
- public boolean equals( Object anObject )
- {
- if ( this == anObject ) return true;
- // assumes only used with other compound keys
- CompoundKey key = (CompoundKey) anObject;
- if ( name == key.name || ( name != null && name.equals( key.name ) ) )
- {
- Object object = get();
- if ( object != null )
- {
- // compares by reference
- if ( object == ( key.get() ) )
- {
- return true;
- }
- }
- }
- return false;
- }
-
- public String toString()
- {
- return "[CompoundKey:"+name()+":"+get()+"]";
- }
- }
-
- /**
- * Value combining an object with a selector.
- * The object is weakly referenced, and null
- * values are not allowed.
- */
- private static class CompoundValue extends WeakReference
- {
- private NSSelector selector;
- private int hashCode;
-
- public CompoundValue( Object anObject, NSSelector aSelector )
- {
- super( anObject );
- hashCode = anObject.hashCode();
- selector = aSelector;
- }
-
- public NSSelector selector()
- {
- return selector;
- }
-
- public int hashCode()
- {
- return hashCode;
- }
-
- public boolean equals( Object anObject )
- {
- if ( this == anObject ) return true;
- // assumes only used with other compound values
- CompoundValue value = (CompoundValue) anObject;
- if ( selector == value.selector ||
- ( selector != null && selector.equals( value.selector ) ) )
- {
- Object object = get();
- if ( object != null )
- {
- if ( object == value.get() )
- {
- return true;
- }
- }
- }
- return false;
- }
-
- public String toString()
- {
- return "[CompoundValue:"+get()+":"+selector().name()+"]";
- }
- }
-/*
- public static void main( String[] argv )
- {
- Object aSource = "aSource";
- Object bSource = "bSource";
-
- Object oneTest = new OneTest();
- Object twoTest = new TwoTest();
- NSSelector notifyMeOnce =
- new NSSelector( "notifyMeOnce",
- new Class[] { NSNotification.class } );
- NSSelector notifyMeTwice =
- new NSSelector( "notifyMeTwice",
- new Class[] { NSNotification.class } );
-
- NSNotificationCenter.defaultCenter().addObserver(
- oneTest, notifyMeOnce, "aMessage", null );
-
- NSNotificationCenter.defaultCenter().addObserver(
- oneTest, notifyMeOnce, null, aSource );
-
- NSNotificationCenter.defaultCenter().addObserver(
- twoTest, notifyMeOnce, "aMessage", aSource );
-
- NSNotificationCenter.defaultCenter().addObserver(
- twoTest, notifyMeTwice, null, null );
-
- NSNotificationCenter.defaultCenter().postNotification(
- "aMessage", aSource );
- System.out.println();
- NSNotificationCenter.defaultCenter().postNotification(
- "aMessage", bSource );
- System.out.println();
- NSNotificationCenter.defaultCenter().postNotification(
- "bMessage", aSource );
- System.out.println();
- NSNotificationCenter.defaultCenter().postNotification(
- "bMessage", bSource );
- System.out.println( "---" );
-
- NSNotificationCenter.defaultCenter().removeObserver(
- oneTest, null, aSource );
-
- NSNotificationCenter.defaultCenter().postNotification(
- "aMessage", aSource );
- System.out.println();
- NSNotificationCenter.defaultCenter().postNotification(
- "aMessage", bSource );
- System.out.println();
- NSNotificationCenter.defaultCenter().postNotification(
- "bMessage", aSource );
- System.out.println();
- NSNotificationCenter.defaultCenter().postNotification(
- "bMessage", bSource );
- System.out.println( "---" );
-
- NSNotificationCenter.defaultCenter().removeObserver(
- null );
-
- NSNotificationCenter.defaultCenter().postNotification(
- "aMessage", aSource );
- System.out.println();
- NSNotificationCenter.defaultCenter().postNotification(
- "aMessage", bSource );
- System.out.println();
- NSNotificationCenter.defaultCenter().postNotification(
- "bMessage", aSource );
- System.out.println();
- NSNotificationCenter.defaultCenter().postNotification(
- "bMessage", bSource );
- System.out.println( "---" );
- }
-
- static private class OneTest
- {
- public void notifyMeOnce( NSNotification aNotification )
- {
- System.out.println( "OneTest.notifyMeOnce: " + aNotification );
- }
- }
-
- static private class TwoTest
- {
- public void notifyMeOnce( NSNotification aNotification )
- {
- System.out.println( "TwoTest.notifyMeOnce: " + aNotification );
- }
- public void notifyMeTwice( NSNotification aNotification )
- {
- System.out.println( "TwoTest.notifyMeTwice: " + aNotification );
- }
- }
-*/
-}
+ * Unregisters the specified observer from all notifications queues associated
+ * with the specified name or object or both.
+ *
+ * @param anObserver The observer to be unregistered, if null will
+ * unregister all observers for the specified
+ * notification name and object.
+ * @param notificationName The name of the notification for which the observer
+ * will be unregistered, if null will unregister the
+ * specified observer for all notifications with the
+ * specified object.
+ * @param anObject The object for the notification for which the
+ * observer will be unregistered, if null will
+ * unregister the specified observer for all objects
+ * with the specified notification.
+ */
+ public void removeObserver(Object anObserver, String notificationName, Object anObject) {
+ // remove freed objects
+ processKeyQueue();
+ // get key matches
+ List keys = matchingKeys(notificationName, anObject);
+ // remove specified observer from each matching key
+ Iterator it = keys.iterator();
+ while (it.hasNext()) {
+ removeObserver(anObserver, it.next());
+ }
+ }
+
+ /**
+ * Returns all keys that match the specified name and object, but in this case
+ * null parameters are considered wildcards. Pass NullMarkers if you want to
+ * explicitly match nulls.
+ */
+ private List matchingKeys(String name, Object object) {
+ List result = new LinkedList();
+
+ boolean willAdd;
+ CompoundKey key;
+ Iterator it = observers.keySet().iterator();
+ while (it.hasNext()) {
+ key = (CompoundKey) it.next();
+ willAdd = false;
+ if ((name == null) || (name == key.name())) {
+ if ((object == null) || (object == key.get())) {
+ willAdd = true;
+ }
+ }
+ if (willAdd) {
+ result.add(key);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Removes the specified observer from the list referenced by the specified key
+ * in the observer map.
+ */
+ private void removeObserver(Object anObserver, Object key) {
+ // if observer null, remove all observers for key
+ if (anObserver == null) {
+ observers.remove(key);
+ return;
+ }
+
+ List list = (List) observers.get(key);
+ if (list == null)
+ return;
+
+ // remove specified observer from list
+ Object observer;
+ Iterator it = list.iterator();
+ while (it.hasNext()) {
+ observer = ((CompoundValue) it.next()).get();
+ if ((observer == null) || (anObserver == observer)) {
+ // remove if match or freed object
+ it.remove();
+
+ // do not return; process entire list
+ }
+ }
+ if (list.size() == 0) {
+ observers.remove(key);
+ }
+ }
+
+ /* Reference queues for cleared WeakKeys */
+ private ReferenceQueue keyQueue = new ReferenceQueue();
+
+ /**
+ * Removes any keys whose object has been garbage collected. (Garbage collected
+ * values are removed as they are encountered.)
+ */
+ private void processKeyQueue() {
+ CompoundKey ck;
+ while ((ck = (CompoundKey) keyQueue.poll()) != null) {
+ // System.out.println( "EOObserverCenter.processQueue: removing object" );
+ observers.remove(ck);
+ }
+ }
+
+ /**
+ * Key combining a name with an object. The object is weakly referenced, and
+ * keys are deallocated by reference queue. equals() compares by reference.
+ */
+ private static class CompoundKey extends WeakReference {
+ private Object name;
+ private int hashCode;
+
+ /**
+ * Creates compound key. Neither name nor object may be null. Use NullMarker to
+ * represent null in either name or object.
+ */
+ public CompoundKey(Object aName, Object anObject) {
+ super(anObject);
+ name = aName;
+ hashCode = aName.hashCode() + anObject.hashCode();
+ }
+
+ /**
+ * Creates compound key with queue. Neither name nor object may be null. Use
+ * NullMarker to represent null in either name or object.
+ */
+ public CompoundKey(Object aName, Object anObject, ReferenceQueue aQueue) {
+ super(anObject, aQueue);
+ name = aName;
+ hashCode = aName.hashCode() + anObject.hashCode();
+ }
+
+ public Object name() {
+ return name;
+ }
+
+ public int hashCode() {
+ return hashCode;
+ }
+
+ public boolean equals(Object anObject) {
+ if (this == anObject)
+ return true;
+ // assumes only used with other compound keys
+ CompoundKey key = (CompoundKey) anObject;
+ if (name == key.name || (name != null && name.equals(key.name))) {
+ Object object = get();
+ if (object != null) {
+ // compares by reference
+ if (object == (key.get())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public String toString() {
+ return "[CompoundKey:" + name() + ":" + get() + "]";
+ }
+ }
+
+ /**
+ * Value combining an object with a selector. The object is weakly referenced,
+ * and null values are not allowed.
+ */
+ private static class CompoundValue extends WeakReference {
+ private NSSelector selector;
+ private int hashCode;
+
+ public CompoundValue(Object anObject, NSSelector aSelector) {
+ super(anObject);
+ hashCode = anObject.hashCode();
+ selector = aSelector;
+ }
+
+ public NSSelector selector() {
+ return selector;
+ }
+
+ public int hashCode() {
+ return hashCode;
+ }
+
+ public boolean equals(Object anObject) {
+ if (this == anObject)
+ return true;
+ // assumes only used with other compound values
+ CompoundValue value = (CompoundValue) anObject;
+ if (selector == value.selector || (selector != null && selector.equals(value.selector))) {
+ Object object = get();
+ if (object != null) {
+ if (object == value.get()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public String toString() {
+ return "[CompoundValue:" + get() + ":" + selector().name() + "]";
+ }
+ }
+ /*
+ * public static void main( String[] argv ) { Object aSource = "aSource"; Object
+ * bSource = "bSource";
+ *
+ * Object oneTest = new OneTest(); Object twoTest = new TwoTest(); NSSelector
+ * notifyMeOnce = new NSSelector( "notifyMeOnce", new Class[] {
+ * NSNotification.class } ); NSSelector notifyMeTwice = new NSSelector(
+ * "notifyMeTwice", new Class[] { NSNotification.class } );
+ *
+ * NSNotificationCenter.defaultCenter().addObserver( oneTest, notifyMeOnce,
+ * "aMessage", null );
+ *
+ * NSNotificationCenter.defaultCenter().addObserver( oneTest, notifyMeOnce,
+ * null, aSource );
+ *
+ * NSNotificationCenter.defaultCenter().addObserver( twoTest, notifyMeOnce,
+ * "aMessage", aSource );
+ *
+ * NSNotificationCenter.defaultCenter().addObserver( twoTest, notifyMeTwice,
+ * null, null );
+ *
+ * NSNotificationCenter.defaultCenter().postNotification( "aMessage", aSource );
+ * System.out.println(); NSNotificationCenter.defaultCenter().postNotification(
+ * "aMessage", bSource ); System.out.println();
+ * NSNotificationCenter.defaultCenter().postNotification( "bMessage", aSource );
+ * System.out.println(); NSNotificationCenter.defaultCenter().postNotification(
+ * "bMessage", bSource ); System.out.println( "---" );
+ *
+ * NSNotificationCenter.defaultCenter().removeObserver( oneTest, null, aSource
+ * );
+ *
+ * NSNotificationCenter.defaultCenter().postNotification( "aMessage", aSource );
+ * System.out.println(); NSNotificationCenter.defaultCenter().postNotification(
+ * "aMessage", bSource ); System.out.println();
+ * NSNotificationCenter.defaultCenter().postNotification( "bMessage", aSource );
+ * System.out.println(); NSNotificationCenter.defaultCenter().postNotification(
+ * "bMessage", bSource ); System.out.println( "---" );
+ *
+ * NSNotificationCenter.defaultCenter().removeObserver( null );
+ *
+ * NSNotificationCenter.defaultCenter().postNotification( "aMessage", aSource );
+ * System.out.println(); NSNotificationCenter.defaultCenter().postNotification(
+ * "aMessage", bSource ); System.out.println();
+ * NSNotificationCenter.defaultCenter().postNotification( "bMessage", aSource );
+ * System.out.println(); NSNotificationCenter.defaultCenter().postNotification(
+ * "bMessage", bSource ); System.out.println( "---" ); }
+ *
+ * static private class OneTest { public void notifyMeOnce( NSNotification
+ * aNotification ) { System.out.println( "OneTest.notifyMeOnce: " +
+ * aNotification ); } }
+ *
+ * static private class TwoTest { public void notifyMeOnce( NSNotification
+ * aNotification ) { System.out.println( "TwoTest.notifyMeOnce: " +
+ * aNotification ); } public void notifyMeTwice( NSNotification aNotification )
+ * { System.out.println( "TwoTest.notifyMeTwice: " + aNotification ); } }
+ */
+}
/*
- * $Log$
- * Revision 1.2 2006/02/16 13:15:00 cgruber
- * Check in all sources in eclipse-friendly maven-enabled packages.
+ * $Log$ Revision 1.2 2006/02/16 13:15:00 cgruber Check in all sources in
+ * eclipse-friendly maven-enabled packages.
*
- * Revision 1.11 2003/06/03 14:51:15 mpowers
- * Added commented-out println for debugging.
+ * Revision 1.11 2003/06/03 14:51:15 mpowers Added commented-out println for
+ * debugging.
*
- * Revision 1.10 2003/03/27 21:46:00 mpowers
- * Better handling for null parameters on subscribe.
- * Better handling for null parameters on post.
+ * Revision 1.10 2003/03/27 21:46:00 mpowers Better handling for null parameters
+ * on subscribe. Better handling for null parameters on post.
*
- * Revision 1.9 2003/01/28 19:44:38 mpowers
- * Now comparing strings by value not reference.
+ * Revision 1.9 2003/01/28 19:44:38 mpowers Now comparing strings by value not
+ * reference.
*
- * Revision 1.8 2001/06/29 16:14:23 mpowers
- * Fixed a javac compiler error that jikes allowed: shoe's on the other foot!
+ * Revision 1.8 2001/06/29 16:14:23 mpowers Fixed a javac compiler error that
+ * jikes allowed: shoe's on the other foot!
*
- * Revision 1.7 2001/06/07 22:09:03 mpowers
- * Exceptions during a notification are no longer being thrown
- * so we can assure that all notifications get handled.
+ * Revision 1.7 2001/06/07 22:09:03 mpowers Exceptions during a notification are
+ * no longer being thrown so we can assure that all notifications get handled.
* Instead, we're printing stack traces...
*
- * Revision 1.6 2001/04/09 21:41:50 mpowers
- * Better debugging.
+ * Revision 1.6 2001/04/09 21:41:50 mpowers Better debugging.
*
- * Revision 1.5 2001/03/15 21:09:06 mpowers
- * Fixed notifications with null objects.
+ * Revision 1.5 2001/03/15 21:09:06 mpowers Fixed notifications with null
+ * objects.
*
- * Revision 1.4 2001/02/21 21:18:34 mpowers
- * Clarified need to retain references.
+ * Revision 1.4 2001/02/21 21:18:34 mpowers Clarified need to retain references.
*
- * Revision 1.3 2001/02/21 18:31:07 mpowers
- * Finished and tested implementation of NSNotificationCenter.
+ * Revision 1.3 2001/02/21 18:31:07 mpowers Finished and tested implementation
+ * of NSNotificationCenter.
*
- * Revision 1.1.1.1 2000/12/21 15:47:39 mpowers
- * Contributing wotonomy.
+ * Revision 1.1.1.1 2000/12/21 15:47:39 mpowers Contributing wotonomy.
*
- * Revision 1.3 2000/12/20 16:25:38 michael
- * Added log to all files.
+ * Revision 1.3 2000/12/20 16:25:38 michael Added log to all files.
*
*
*/
-