com.taco.data
Class ObservableMap

java.lang.Object
  extended by java.util.AbstractMap
      extended by com.taco.data.AbstractNoReturnMap
          extended by com.taco.data.ObservableMap
All Implemented Interfaces:
INoReturnMap, INoReturnObservableMap, IObservableMap, java.io.Serializable, java.lang.Cloneable, java.util.Map

public class ObservableMap
extends AbstractNoReturnMap
implements INoReturnObservableMap, java.lang.Cloneable, java.io.Serializable

A concrete implementation of IObservableMap.

This class decorates another map which provides the storage. If the the decorated map is an instance of INoReturnMap, this class will call putNoReturn() and removeNoReturn() on the decorated map instead of put() and remove() whenever possible.

This class attempts to prevent infinite recursion in the following situation: When a single thread calls put(key, value, true), a listener is notified of a change on the same thread. The listener attempts to put the same value in the map again. (This might happen if the listener updates a component, and on update the component notifies its listeners. One of its listeners might be a map consistency listener which updates the map in response to the component property change). Thus the recursion cycle is complete. This class breaks the cycle by keeping track of the keys that are being put at any given time. Before the value associated with a key is changed, the key is added to a put key set. If during the notification of listeners, someone attempts to put the same key in the map (with any value), the put operation will silently return without doing anything. This only works if everything occurs in the same thread. If this is not the case, it is up to listeners to detect infinite recursion and break the recursion cycle.

This class is not safe for use by multiple threads.

See Also:
Serialized Form

Nested Class Summary
protected  class ObservableMap.EntrySet
          The set used as the entry set of the map.
protected static class ObservableMap.ValueElement
          The data structure that is used for map values.
 
Nested classes/interfaces inherited from class com.taco.data.AbstractNoReturnMap
AbstractNoReturnMap.NoReturnEntry, AbstractNoReturnMap.NoReturnEntrySet, AbstractNoReturnMap.NoReturnIterator
 
Nested classes/interfaces inherited from interface com.taco.data.INoReturnObservableMap
INoReturnObservableMap.INoReturnObservableEntry
 
Nested classes/interfaces inherited from interface com.taco.data.INoReturnMap
INoReturnMap.INoReturnEntry
 
Nested classes/interfaces inherited from interface java.util.Map
java.util.Map.Entry
 
Nested classes/interfaces inherited from interface com.taco.data.IObservableMap
IObservableMap.IObservableEntry
 
Nested classes/interfaces inherited from interface java.util.Map
java.util.Map.Entry
 
Field Summary
protected  java.util.Set _cachedEntrySet
          The entry set, lazily computed and cached.
protected  java.util.Map _map
          The map that provides the underlying storage.
protected  IMapFactory _mapFactory
          The factory used to create new maps and copies of maps.
protected  INoReturnMap _noReturnMap
          If _map is an instance of INoReturnMap, this is a casted copy of _map.
protected  INotificationStrategy _notificationStrategy
          The strategy that specifies how to notify listeners.
protected  java.util.Collection _putKeys
          A set of keys that have been put so far in the current call stack.
 
Fields inherited from class com.taco.data.AbstractNoReturnMap
_cachedNoReturnEntrySet
 
Fields inherited from interface com.taco.data.IObservableMap
SINGLE_THREADED_STRATEGY
 
Constructor Summary
  ObservableMap()
          Create a new instance that uses a hash map factory, with a initial size of 16 entries, and a single-threaded notification strategy.
  ObservableMap(IMapFactory mapFactory, int capacity, INotificationStrategy notificationStrategy)
          Construct a new instance that uses the argument factory to create a new map that provides storage for the new instance.
  ObservableMap(INotificationStrategy notificationStrategy)
          Create a new instance that uses a hash map factory, with a initial size of 16 entries, and the argument notification strategy.
  ObservableMap(java.util.Map map)
          Create a new instance that uses a hash map factory to make a copy of the argument map and a single-threaded notification strategy.
  ObservableMap(java.util.Map map, IMapFactory mapFactory, INotificationStrategy notificationStrategy)
           
protected ObservableMap(ObservableMap observableMap)
          Create a new instance that uses a clone of the argument map's storage map for its own storage.
 
Method Summary
protected  void _notifyListeners(java.lang.Object key, java.lang.Object oldValue, java.lang.Object newValue, java.util.Collection listeners, IObjectFilter listenerFilter)
          Notify all listeners of the change in the value mapped to the argument key.
 void addPropertyChangeListener(java.lang.String key, java.beans.PropertyChangeListener listener)
          Add listener to the list of listeners for changes to the value mapped to key.
 void clear()
           
 java.lang.Object clone()
           
 boolean containsKey(java.lang.Object key)
           
 boolean containsValue(java.lang.Object value)
           
 java.util.Set entrySet()
           
 java.lang.Object get(java.lang.Object key)
           
 INotificationStrategy getNotificationStrategy()
          Return the strategy used to notify listeners.
 java.util.Collection getPropertyChangeListeners(java.lang.String key)
          Return a collection of the property change listeners for the argument key.
 boolean isEmpty()
           
 java.util.Set keySet()
           
 java.lang.Object put(java.lang.Object key, java.lang.Object value)
          Call put(key, value, AcceptAllObjectFilter.instance) (notify all listeners).
 java.lang.Object put(java.lang.Object key, java.lang.Object value, boolean notifyListeners)
          Associate value with key in the map.
 java.lang.Object put(java.lang.Object key, java.lang.Object value, IObjectFilter listenerFilter)
          Put the key-value pair in the map.
 void putAll(java.util.Map sourceMap)
          Call putAll(sourceMap, true) (notify listeners).
 void putAll(java.util.Map sourceMap, boolean notifyListeners)
          Put all key / value pairs in the argument map in this map.
 void putAll(java.util.Map sourceMap, IObjectFilter filter)
          Copy all of the mappings from the specified map to this map.
 void putNoReturn(java.lang.Object key, java.lang.Object value)
          Call putNoReturn(key, value, true) (notify all listeners).
 void putNoReturn(java.lang.Object key, java.lang.Object value, boolean notifyListeners)
          Associate value with key in the map.
 void putNoReturn(java.lang.Object key, java.lang.Object value, IObjectFilter listenerFilter)
           
 java.lang.Object remove(java.lang.Object key)
           
 void removeNoReturn(java.lang.Object key)
          This implementation simply calls remove() -- there is no speed advantage to using this method.
 void removePropertyChangeListener(java.lang.String key, java.beans.PropertyChangeListener listener)
          If listener is a listener for the argument key, remove it from the list of listeners for the key.
 void setNotificationStrategy(INotificationStrategy strategy)
          Set the strategy used to notify listeners.
 void setPropertyChangeListeners(java.lang.String key, java.util.Collection listeners)
          Set the collection of listeners to be notified when the value associated with key is changed.
 int size()
           
 
Methods inherited from class com.taco.data.AbstractNoReturnMap
entrySetNoReturn
 
Methods inherited from class java.util.AbstractMap
equals, hashCode, toString, values
 
Methods inherited from class java.lang.Object
finalize, getClass, notify, notifyAll, wait, wait, wait
 
Methods inherited from interface com.taco.data.INoReturnMap
entrySetNoReturn
 
Methods inherited from interface java.util.Map
equals, hashCode, values
 
Methods inherited from interface java.util.Map
equals, hashCode, values
 

Field Detail

_mapFactory

protected IMapFactory _mapFactory
The factory used to create new maps and copies of maps.


_map

protected java.util.Map _map
The map that provides the underlying storage.


_noReturnMap

protected INoReturnMap _noReturnMap
If _map is an instance of INoReturnMap, this is a casted copy of _map.


_notificationStrategy

protected INotificationStrategy _notificationStrategy
The strategy that specifies how to notify listeners.


_putKeys

protected java.util.Collection _putKeys
A set of keys that have been put so far in the current call stack. If a key is put once, and a notified listeners attempts to put the key again, the second put will do nothing. This prevents infinite recursion. Unfortunately, the values that are put are not checked, so if the response to putting a key's value is to put a different value for the key, the response will be lost. This is not final so that instances of this class can be cloned.


_cachedEntrySet

protected transient java.util.Set _cachedEntrySet
The entry set, lazily computed and cached. The set has no state even though iterators returned by it do. So it suffices to compute the entry set once.

Constructor Detail

ObservableMap

public ObservableMap()
Create a new instance that uses a hash map factory, with a initial size of 16 entries, and a single-threaded notification strategy.


ObservableMap

public ObservableMap(INotificationStrategy notificationStrategy)
Create a new instance that uses a hash map factory, with a initial size of 16 entries, and the argument notification strategy.


ObservableMap

public ObservableMap(IMapFactory mapFactory,
                     int capacity,
                     INotificationStrategy notificationStrategy)
Construct a new instance that uses the argument factory to create a new map that provides storage for the new instance.


ObservableMap

public ObservableMap(java.util.Map map)
Create a new instance that uses a hash map factory to make a copy of the argument map and a single-threaded notification strategy.


ObservableMap

public ObservableMap(java.util.Map map,
                     IMapFactory mapFactory,
                     INotificationStrategy notificationStrategy)

ObservableMap

protected ObservableMap(ObservableMap observableMap)
Create a new instance that uses a clone of the argument map's storage map for its own storage.

Method Detail

clone

public java.lang.Object clone()
                       throws java.lang.CloneNotSupportedException
Overrides:
clone in class java.util.AbstractMap
Throws:
java.lang.CloneNotSupportedException

clear

public void clear()
Specified by:
clear in interface java.util.Map
Overrides:
clear in class java.util.AbstractMap

containsKey

public boolean containsKey(java.lang.Object key)
Specified by:
containsKey in interface java.util.Map
Overrides:
containsKey in class java.util.AbstractMap

containsValue

public boolean containsValue(java.lang.Object value)
Specified by:
containsValue in interface java.util.Map
Overrides:
containsValue in class java.util.AbstractMap

entrySet

public java.util.Set entrySet()
Specified by:
entrySet in interface java.util.Map
Specified by:
entrySet in class java.util.AbstractMap

get

public java.lang.Object get(java.lang.Object key)
Specified by:
get in interface java.util.Map
Overrides:
get in class java.util.AbstractMap

isEmpty

public boolean isEmpty()
Specified by:
isEmpty in interface java.util.Map
Overrides:
isEmpty in class java.util.AbstractMap

keySet

public java.util.Set keySet()
Specified by:
keySet in interface java.util.Map
Overrides:
keySet in class java.util.AbstractMap

put

public java.lang.Object put(java.lang.Object key,
                            java.lang.Object value)
Call put(key, value, AcceptAllObjectFilter.instance) (notify all listeners).

Specified by:
put in interface IObservableMap
Specified by:
put in interface java.util.Map
Overrides:
put in class java.util.AbstractMap

putNoReturn

public void putNoReturn(java.lang.Object key,
                        java.lang.Object value)
Call putNoReturn(key, value, true) (notify all listeners).

Specified by:
putNoReturn in interface INoReturnMap
Overrides:
putNoReturn in class AbstractNoReturnMap

put

public java.lang.Object put(java.lang.Object key,
                            java.lang.Object value,
                            boolean notifyListeners)
Associate value with key in the map. If there are any listeners of changes to the values mapped by the argument key, notify them via _notifyListeners(). If the value is being put already somewhere in the call stack, return null.

Specified by:
put in interface IObservableMap
Parameters:
notifyListeners - If true, notify listeners of the change.

put

public java.lang.Object put(java.lang.Object key,
                            java.lang.Object value,
                            IObjectFilter listenerFilter)
Description copied from interface: IObservableMap
Put the key-value pair in the map. Notify all listeners for the argument key that are accepted by the filter of of the change.

Specified by:
put in interface IObservableMap

putNoReturn

public void putNoReturn(java.lang.Object key,
                        java.lang.Object value,
                        boolean notifyListeners)
Associate value with key in the map. If there are any listeners of changes to the values mapped by the argument key, notify them via _notifyListeners().

Specified by:
putNoReturn in interface INoReturnObservableMap
Parameters:
notifyListeners - If true, notify listeners of the change.

putNoReturn

public void putNoReturn(java.lang.Object key,
                        java.lang.Object value,
                        IObjectFilter listenerFilter)
Specified by:
putNoReturn in interface INoReturnObservableMap

putAll

public void putAll(java.util.Map sourceMap)
Call putAll(sourceMap, true) (notify listeners).

Specified by:
putAll in interface INoReturnMap
Specified by:
putAll in interface IObservableMap
Specified by:
putAll in interface java.util.Map
Overrides:
putAll in class AbstractNoReturnMap
Throws:
java.lang.NullPointerException - if sourceMap is null.

putAll

public void putAll(java.util.Map sourceMap,
                   boolean notifyListeners)
Put all key / value pairs in the argument map in this map.

Specified by:
putAll in interface IObservableMap
Parameters:
notifyListeners - If true, notify listeners of the change.
Throws:
java.lang.NullPointerException - if sourceMap is null.

putAll

public void putAll(java.util.Map sourceMap,
                   IObjectFilter filter)
Description copied from interface: IObservableMap
Copy all of the mappings from the specified map to this map. If notifyListeners is true, notify all listeners of the affected keys that are accepted by the filter of the changes.

Specified by:
putAll in interface IObservableMap

remove

public java.lang.Object remove(java.lang.Object key)
Specified by:
remove in interface java.util.Map
Overrides:
remove in class java.util.AbstractMap

removeNoReturn

public void removeNoReturn(java.lang.Object key)
Description copied from class: AbstractNoReturnMap
This implementation simply calls remove() -- there is no speed advantage to using this method.

Specified by:
removeNoReturn in interface INoReturnMap
Overrides:
removeNoReturn in class AbstractNoReturnMap

size

public int size()
Specified by:
size in interface java.util.Map
Overrides:
size in class java.util.AbstractMap

addPropertyChangeListener

public void addPropertyChangeListener(java.lang.String key,
                                      java.beans.PropertyChangeListener listener)
Add listener to the list of listeners for changes to the value mapped to key. If no value is mapped to key yet, map null to it now.

Specified by:
addPropertyChangeListener in interface IObservableMap

removePropertyChangeListener

public void removePropertyChangeListener(java.lang.String key,
                                         java.beans.PropertyChangeListener listener)
If listener is a listener for the argument key, remove it from the list of listeners for the key. Otherwise, fail silently.

Specified by:
removePropertyChangeListener in interface IObservableMap

getPropertyChangeListeners

public java.util.Collection getPropertyChangeListeners(java.lang.String key)
Return a collection of the property change listeners for the argument key. The returned list is a copy of the collection stored internally so it may be modified by the caller.

Specified by:
getPropertyChangeListeners in interface IObservableMap

setPropertyChangeListeners

public void setPropertyChangeListeners(java.lang.String key,
                                       java.util.Collection listeners)
Set the collection of listeners to be notified when the value associated with key is changed. Make a copy of the listener collection so the user is free to modify it afterwards.

Specified by:
setPropertyChangeListeners in interface IObservableMap

getNotificationStrategy

public INotificationStrategy getNotificationStrategy()
Return the strategy used to notify listeners.

Specified by:
getNotificationStrategy in interface IObservableMap

setNotificationStrategy

public void setNotificationStrategy(INotificationStrategy strategy)
Set the strategy used to notify listeners.

Specified by:
setNotificationStrategy in interface IObservableMap
Throws:
java.lang.NullPointerException - if the argument strategy is null.

_notifyListeners

protected void _notifyListeners(java.lang.Object key,
                                java.lang.Object oldValue,
                                java.lang.Object newValue,
                                java.util.Collection listeners,
                                IObjectFilter listenerFilter)
Notify all listeners of the change in the value mapped to the argument key.

Parameters:
key - The map key whose value is changed.
oldValue - The old value mapped to the key, null if unknown.
newValue - The new value mapped to the key.
listeners - A collection of property change listeners of the changes to value mapped to key.