001    /*
002     * Copyright 2003-2004 The Apache Software Foundation
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *     http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.apache.commons.events.observable;
017    
018    import java.util.Comparator;
019    
020    import org.apache.commons.collections.SortedBag;
021    
022    /**
023     * Decorates a <code>SortedBag</code> implementation to observe modifications.
024     * <p>
025     * Each modifying method call made on this <code>SortedBag</code> is forwarded to a
026     * {@link ModificationHandler}.
027     * The handler manages the event, notifying listeners and optionally vetoing changes.
028     * The default handler is
029     * {@link org.apache.commons.events.observable.standard.StandardModificationHandler StandardModificationHandler}.
030     * See this class for details of configuration available.
031     *
032     * @since Commons Events 1.0
033     * @version $Revision: 155443 $ $Date: 2005-02-26 13:19:51 +0000 (Sat, 26 Feb 2005) $
034     * 
035     * @author Stephen Colebourne
036     */
037    public class ObservableSortedBag extends ObservableBag implements SortedBag {
038        
039        // Factories
040        //-----------------------------------------------------------------------
041        /**
042         * Factory method to create an observable bag.
043         * <p>
044         * A {@link org.apache.commons.events.observable.standard.StandardModificationHandler} will be created.
045         * This can be accessed by {@link #getHandler()} to add listeners.
046         *
047         * @param bag  the bag to decorate, must not be null
048         * @return the observed bag
049         * @throws IllegalArgumentException if the collection is null
050         */
051        public static ObservableSortedBag decorate(final SortedBag bag) {
052            return new ObservableSortedBag(bag, null);
053        }
054    
055        /**
056         * Factory method to create an observable bag using a listener or a handler.
057         * <p>
058         * A lot of functionality is available through this method.
059         * If you don't need the extra functionality, simply implement the
060         * {@link org.apache.commons.events.observable.standard.StandardModificationListener}
061         * interface and pass it in as the second parameter.
062         * <p>
063         * Internally, an <code>ObservableSortedBag</code> relies on a {@link ModificationHandler}.
064         * The handler receives all the events and processes them, typically by
065         * calling listeners. Different handler implementations can be plugged in
066         * to provide a flexible event system.
067         * <p>
068         * The handler implementation is determined by the listener parameter via
069         * the registered factories. The listener may be a manually configured 
070         * <code>ModificationHandler</code> instance.
071         * <p>
072         * The listener is defined as an Object for maximum flexibility.
073         * It does not have to be a listener in the classic JavaBean sense.
074         * It is entirely up to the factory and handler as to how the parameter
075         * is interpretted. An IllegalArgumentException is thrown if no suitable
076         * handler can be found for this listener.
077         * <p>
078         * A <code>null</code> listener will create a
079         * {@link org.apache.commons.events.observable.standard.StandardModificationHandler}.
080         *
081         * @param bag  the bag to decorate, must not be null
082         * @param listener  bag listener, may be null
083         * @return the observed bag
084         * @throws IllegalArgumentException if the bag is null
085         * @throws IllegalArgumentException if there is no valid handler for the listener
086         */
087        public static ObservableSortedBag decorate(
088                final SortedBag bag,
089                final Object listener) {
090            
091            if (bag == null) {
092                throw new IllegalArgumentException("SortedBag must not be null");
093            }
094            return new ObservableSortedBag(bag, listener);
095        }
096    
097        // Constructors
098        //-----------------------------------------------------------------------
099        /**
100         * Constructor that wraps (not copies) and takes a handler.
101         * <p>
102         * The handler implementation is determined by the listener parameter via
103         * the registered factories. The listener may be a manually configured 
104         * <code>ModificationHandler</code> instance.
105         * 
106         * @param bag  the bag to decorate, must not be null
107         * @param listener  the listener, may be null
108         * @throws IllegalArgumentException if the bag is null
109         */
110        protected ObservableSortedBag(
111                final SortedBag bag,
112                final Object listener) {
113            super(bag, listener);
114        }
115    
116        /**
117         * Typecast the collection to a SortedBag.
118         * 
119         * @return the wrapped collection as a SortedBag
120         */
121        private SortedBag getSortedBag() {
122            return (SortedBag) getCollection();
123        }
124    
125        // SortedBag API
126        //-----------------------------------------------------------------------
127        public Comparator comparator() {
128            return getSortedBag().comparator();
129        }
130    
131        public Object first() {
132            return getSortedBag().first();
133        }
134    
135        public Object last() {
136            return getSortedBag().last();
137        }
138    
139    }