package org.apache.commons.events.observable ; import java.util.SortedMap ; import java.util.Comparator ; /** *
* Decorates a SortedMap
implementation with a bound
* property named "collection".
*
* Each modifying method call made on this SortedMap
is
* handled as a change to the "collection" property. This
* facility serves to notify subscribers of a change to the collection
* but does not allow users the option of vetoing the change. To
* gain the ability to veto the change, use a {@link ConstrainedSortedMap}
* decorater.
*
* Due to the fact that a Map offers several "views" of the
* same data, some confusion may arise as to what action caused a
* particular event. For instance, entries in the map may be
* deleted by Map.values().remove(object)
. There is no
* known method, short of digging into the implementation of a Map,
* to determine which key-value pair was deleted by this operation,
* particularly if there is more than one occurence of a specific
* value. (Conversely, there is also no means of controlling which
* key-value pair is deleted by this method; therefore it's not a
* terribly smart thing to do.)
*
* This implementation of a bound map makes no attempt to interpret * events generated by these alternate views of the data. It merely * ensures that registered listeners receive all events generated * by any view of the Map's data. It is left to the client * to interpret the events generated by their map's usage. *
* * @see BoundMap * @since Commons Events 1.0 * @author Bryce Nordgren / USDA Forest Service */ public class BoundSortedMap extends BoundMap implements SortedMap { // Constructors //----------------------------------------------------------------------- protected BoundSortedMap( final SortedMap source, final CollectionChangeEventFactory eventFactory) { super(source, eventFactory) ; } protected BoundSortedMap(final SortedMap source) { super(source); } // Factory methods //----------------------------------------------------------------------- public static BoundSortedMap decorate( final SortedMap source, final CollectionChangeEventFactory eventFactory) { return new BoundSortedMap(source, eventFactory) ; } public static BoundSortedMap decorate(final SortedMap source) { return new BoundSortedMap(source) ; } // Utility methods //----------------------------------------------------------------------- /** * Typecast to the SortedMap interface... * @return a SortedMap */ private SortedMap getSortedMap() { return (SortedMap)(getMap()) ; } /** * Binds an unbound SortedMap returned by the decorated object. * Ensures that this map and the newly bound map get each other's * events. */ private SortedMap bindSortedMap(SortedMap unbound) { // make a copy of the event factory CollectionChangeEventFactory factoryCopy = (CollectionChangeEventFactory)(eventFactory.clone()) ; // bind the subMap view BoundSortedMap boundMap = BoundSortedMap.decorate( unbound, factoryCopy) ; // send "boundMap's" events to our listeners boundMap.addPropertyChangeListener(createEventRepeater()) ; // send our events to "boundMap's" listeners addPropertyChangeListener(boundMap.createEventRepeater()) ; return boundMap ; } // SortedMap API (methods which do not change map contents.) //----------------------------------------------------------------------- public Comparator comparator() { return getSortedMap().comparator() ; } public Object firstKey() { return getSortedMap().firstKey() ; } public Object lastKey() { return getSortedMap().lastKey() ; } // Decorator methods //----------------------------------------------------------------------- public SortedMap subMap(Object fromKey, Object toKey) { SortedMap subMap = getSortedMap().subMap(fromKey, toKey) ; return bindSortedMap(subMap) ; } public SortedMap headMap(Object toKey) { SortedMap subMap = getSortedMap().headMap(toKey) ; return bindSortedMap(subMap) ; } public SortedMap tailMap(Object fromKey) { SortedMap subMap = getSortedMap().tailMap(fromKey) ; return bindSortedMap(subMap) ; } }