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    import java.util.SortedSet;
020    
021    /**
022     * Decorates a <code>SortedSet</code> implementation to observe modifications.
023     * <p>
024     * Each modifying method call made on this <code>SortedSet</code> is forwarded to a
025     * {@link ModificationHandler}.
026     * The handler manages the event, notifying listeners and optionally vetoing changes.
027     * The default handler is
028     * {@link org.apache.commons.events.observable.standard.StandardModificationHandler StandardModificationHandler}.
029     * See this class for details of configuration available.
030     *
031     * @since Commons Events 1.0
032     * @version $Revision: 155443 $ $Date: 2005-02-26 13:19:51 +0000 (Sat, 26 Feb 2005) $
033     * 
034     * @author Stephen Colebourne
035     */
036    public class ObservableSortedSet extends ObservableSet implements SortedSet {
037        
038        // Factories
039        //-----------------------------------------------------------------------
040        /**
041         * Factory method to create an observable set.
042         * <p>
043         * A {@link org.apache.commons.events.observable.standard.StandardModificationHandler} will be created.
044         * This can be accessed by {@link #getHandler()} to add listeners.
045         *
046         * @param set  the set to decorate, must not be null
047         * @return the observed Set
048         * @throws IllegalArgumentException if the collection is null
049         */
050        public static ObservableSortedSet decorate(final SortedSet set) {
051            return new ObservableSortedSet(set, null);
052        }
053    
054        /**
055         * Factory method to create an observable set using a listener or a handler.
056         * <p>
057         * A lot of functionality is available through this method.
058         * If you don't need the extra functionality, simply implement the
059         * {@link org.apache.commons.events.observable.standard.StandardModificationListener}
060         * interface and pass it in as the second parameter.
061         * <p>
062         * Internally, an <code>ObservableSortedSet</code> relies on a {@link ModificationHandler}.
063         * The handler receives all the events and processes them, typically by
064         * calling listeners. Different handler implementations can be plugged in
065         * to provide a flexible event system.
066         * <p>
067         * The handler implementation is determined by the listener parameter via
068         * the registered factories. The listener may be a manually configured 
069         * <code>ModificationHandler</code> instance.
070         * <p>
071         * The listener is defined as an Object for maximum flexibility.
072         * It does not have to be a listener in the classic JavaBean sense.
073         * It is entirely up to the factory and handler as to how the parameter
074         * is interpretted. An IllegalArgumentException is thrown if no suitable
075         * handler can be found for this listener.
076         * <p>
077         * A <code>null</code> listener will create a
078         * {@link org.apache.commons.events.observable.standard.StandardModificationHandler}.
079         *
080         * @param set  the set to decorate, must not be null
081         * @param listener  set listener, may be null
082         * @return the observed set
083         * @throws IllegalArgumentException if the set is null
084         * @throws IllegalArgumentException if there is no valid handler for the listener
085         */
086        public static ObservableSortedSet decorate(
087                final SortedSet set,
088                final Object listener) {
089            
090            if (set == null) {
091                throw new IllegalArgumentException("SortedSet must not be null");
092            }
093            return new ObservableSortedSet(set, listener);
094        }
095    
096        // Constructors
097        //-----------------------------------------------------------------------
098        /**
099         * Constructor that wraps (not copies) and takes a handler.
100         * <p>
101         * The handler implementation is determined by the listener parameter via
102         * the registered factories. The listener may be a manually configured 
103         * <code>ModificationHandler</code> instance.
104         * 
105         * @param set  the set to decorate, must not be null
106         * @param listener  the listener, may be null
107         * @throws IllegalArgumentException if the set is null
108         */
109        protected ObservableSortedSet(
110                final SortedSet set,
111                final Object listener) {
112            super(set, listener);
113        }
114    
115        /**
116         * Typecast the collection to a SortedSet.
117         * 
118         * @return the wrapped collection as a SortedSet
119         */
120        private SortedSet getSortedSet() {
121            return (SortedSet) getCollection();
122        }
123    
124        // SortedSet API
125        //-----------------------------------------------------------------------
126        public Comparator comparator() {
127            return getSortedSet().comparator();
128        }
129    
130        public Object first() {
131            return getSortedSet().first();
132        }
133    
134        public Object last() {
135            return getSortedSet().last();
136        }
137    
138        //-----------------------------------------------------------------------
139        public SortedSet subSet(Object fromElement, Object toElement) {
140            SortedSet subSet = getSortedSet().subSet(fromElement, toElement);
141            return new ObservableSortedSet(subSet, getHandler().createSubSetHandler(fromElement, toElement));
142        }
143    
144        public SortedSet headSet(Object toElement) {
145            SortedSet headSet = getSortedSet().headSet(toElement);
146            return new ObservableSortedSet(headSet, getHandler().createHeadSetHandler(toElement));
147        }
148    
149        public SortedSet tailSet(Object fromElement) {
150            SortedSet tailSet = getSortedSet().tailSet(fromElement);
151            return new ObservableSortedSet(tailSet, getHandler().createTailSetHandler(fromElement));
152        }
153    
154    }