KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > collections > set > ListOrderedSet


1 /*
2  * Copyright 2003-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.collections.set;
17
18 import java.util.ArrayList JavaDoc;
19 import java.util.Collection JavaDoc;
20 import java.util.HashSet JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Set JavaDoc;
24
25 import org.apache.commons.collections.iterators.AbstractIteratorDecorator;
26 import org.apache.commons.collections.list.UnmodifiableList;
27
28 /**
29  * Decorates another <code>Set</code> to ensure that the order of addition
30  * is retained and used by the iterator.
31  * <p>
32  * If an object is added to the set for a second time, it will remain in the
33  * original position in the iteration.
34  * The order can be observed from the set via the iterator or toArray methods.
35  * <p>
36  * The ListOrderedSet also has various useful direct methods. These include many
37  * from <code>List</code>, such as <code>get(int)</code>, <code>remove(int)</code>
38  * and <code>indexOf(int)</code>. An unmodifiable <code>List</code> view of
39  * the set can be obtained via <code>asList()</code>.
40  * <p>
41  * This class cannot implement the <code>List</code> interface directly as
42  * various interface methods (notably equals/hashCode) are incompatable with a set.
43  * <p>
44  * This class is Serializable from Commons Collections 3.1.
45  *
46  * @since Commons Collections 3.0
47  * @version $Revision: 1.9 $ $Date: 2004/06/07 21:42:12 $
48  *
49  * @author Stephen Colebourne
50  * @author Henning P. Schmiedehausen
51  */

52 public class ListOrderedSet extends AbstractSerializableSetDecorator implements Set JavaDoc {
53
54     /** Serialization version */
55     private static final long serialVersionUID = -228664372470420141L;
56
57     /** Internal list to hold the sequence of objects */
58     protected final List JavaDoc setOrder;
59
60     /**
61      * Factory method to create an ordered set specifying the list and set to use.
62      *
63      * @param set the set to decorate, must be empty and not null
64      * @param list the list to decorate, must be empty and not null
65      * @throws IllegalArgumentException if set or list is null
66      * @throws IllegalArgumentException if either the set or list is not empty
67      * @since Commons Collections 3.1
68      */

69     public static ListOrderedSet decorate(Set JavaDoc set, List JavaDoc list) {
70         if (set == null) {
71             throw new IllegalArgumentException JavaDoc("Set must not be null");
72         }
73         if (list == null) {
74             throw new IllegalArgumentException JavaDoc("List must not be null");
75         }
76         if (set.size() > 0 || list.size() > 0) {
77             throw new IllegalArgumentException JavaDoc("Set and List must be empty");
78         }
79         return new ListOrderedSet(set, list);
80     }
81
82     /**
83      * Factory method to create an ordered set.
84      * <p>
85      * An <code>ArrayList</code> is used to retain order.
86      *
87      * @param set the set to decorate, must not be null
88      * @throws IllegalArgumentException if set is null
89      */

90     public static ListOrderedSet decorate(Set JavaDoc set) {
91         return new ListOrderedSet(set);
92     }
93
94     /**
95      * Factory method to create an ordered set using the supplied list to retain order.
96      * <p>
97      * A <code>HashSet</code> is used for the set behaviour.
98      *
99      * @param list the list to decorate, must not be null
100      * @throws IllegalArgumentException if list is null
101      */

102     public static ListOrderedSet decorate(List JavaDoc list) {
103         if (list == null) {
104             throw new IllegalArgumentException JavaDoc("List must not be null");
105         }
106         Set JavaDoc set = new HashSet JavaDoc(list);
107         list.retainAll(set);
108         
109         return new ListOrderedSet(set, list);
110     }
111
112     //-----------------------------------------------------------------------
113
/**
114      * Constructs a new empty <code>ListOrderedSet</code> using
115      * a <code>HashSet</code> and an <code>ArrayList</code> internally.
116      *
117      * @since Commons Collections 3.1
118      */

119     public ListOrderedSet() {
120         super(new HashSet JavaDoc());
121         setOrder = new ArrayList JavaDoc();
122     }
123
124     /**
125      * Constructor that wraps (not copies).
126      *
127      * @param set the set to decorate, must not be null
128      * @throws IllegalArgumentException if set is null
129      */

130     protected ListOrderedSet(Set JavaDoc set) {
131         super(set);
132         setOrder = new ArrayList JavaDoc(set);
133     }
134
135     /**
136      * Constructor that wraps (not copies) the Set and specifies the list to use.
137      * <p>
138      * The set and list must both be correctly initialised to the same elements.
139      *
140      * @param set the set to decorate, must not be null
141      * @param list the list to decorate, must not be null
142      * @throws IllegalArgumentException if set or list is null
143      */

144     protected ListOrderedSet(Set JavaDoc set, List JavaDoc list) {
145         super(set);
146         if (list == null) {
147             throw new IllegalArgumentException JavaDoc("List must not be null");
148         }
149         setOrder = list;
150     }
151
152     //-----------------------------------------------------------------------
153
/**
154      * Gets an unmodifiable view of the order of the Set.
155      *
156      * @return an unmodifiable list view
157      */

158     public List JavaDoc asList() {
159         return UnmodifiableList.decorate(setOrder);
160     }
161
162     //-----------------------------------------------------------------------
163
public void clear() {
164         collection.clear();
165         setOrder.clear();
166     }
167
168     public Iterator JavaDoc iterator() {
169         return new OrderedSetIterator(setOrder.iterator(), collection);
170     }
171
172     public boolean add(Object JavaDoc object) {
173         if (collection.contains(object)) {
174             // re-adding doesn't change order
175
return collection.add(object);
176         } else {
177             // first add, so add to both set and list
178
boolean result = collection.add(object);
179             setOrder.add(object);
180             return result;
181         }
182     }
183
184     public boolean addAll(Collection JavaDoc coll) {
185         boolean result = false;
186         for (Iterator JavaDoc it = coll.iterator(); it.hasNext();) {
187             Object JavaDoc object = it.next();
188             result = result | add(object);
189         }
190         return result;
191     }
192
193     public boolean remove(Object JavaDoc object) {
194         boolean result = collection.remove(object);
195         setOrder.remove(object);
196         return result;
197     }
198
199     public boolean removeAll(Collection JavaDoc coll) {
200         boolean result = false;
201         for (Iterator JavaDoc it = coll.iterator(); it.hasNext();) {
202             Object JavaDoc object = it.next();
203             result = result | remove(object);
204         }
205         return result;
206     }
207
208     public boolean retainAll(Collection JavaDoc coll) {
209         boolean result = collection.retainAll(coll);
210         if (result == false) {
211             return false;
212         } else if (collection.size() == 0) {
213             setOrder.clear();
214         } else {
215             for (Iterator JavaDoc it = setOrder.iterator(); it.hasNext();) {
216                 Object JavaDoc object = it.next();
217                 if (collection.contains(object) == false) {
218                     it.remove();
219                 }
220             }
221         }
222         return result;
223     }
224
225     public Object JavaDoc[] toArray() {
226         return setOrder.toArray();
227     }
228
229     public Object JavaDoc[] toArray(Object JavaDoc a[]) {
230         return setOrder.toArray(a);
231     }
232
233     //-----------------------------------------------------------------------
234
public Object JavaDoc get(int index) {
235         return setOrder.get(index);
236     }
237
238     public int indexOf(Object JavaDoc object) {
239         return setOrder.indexOf(object);
240     }
241
242     public void add(int index, Object JavaDoc object) {
243         if (contains(object) == false) {
244             collection.add(object);
245             setOrder.add(index, object);
246         }
247     }
248
249     public boolean addAll(int index, Collection JavaDoc coll) {
250         boolean changed = false;
251         for (Iterator JavaDoc it = coll.iterator(); it.hasNext();) {
252             Object JavaDoc object = it.next();
253             if (contains(object) == false) {
254                 collection.add(object);
255                 setOrder.add(index, object);
256                 index++;
257                 changed = true;
258             }
259         }
260         return changed;
261     }
262
263     public Object JavaDoc remove(int index) {
264         Object JavaDoc obj = setOrder.remove(index);
265         remove(obj);
266         return obj;
267     }
268
269     /**
270      * Uses the underlying List's toString so that order is achieved.
271      * This means that the decorated Set's toString is not used, so
272      * any custom toStrings will be ignored.
273      */

274     // Fortunately List.toString and Set.toString look the same
275
public String JavaDoc toString() {
276         return setOrder.toString();
277     }
278
279     //-----------------------------------------------------------------------
280
/**
281      * Internal iterator handle remove.
282      */

283     static class OrderedSetIterator extends AbstractIteratorDecorator {
284         
285         /** Object we iterate on */
286         protected final Collection JavaDoc set;
287         /** Last object retrieved */
288         protected Object JavaDoc last;
289
290         private OrderedSetIterator(Iterator JavaDoc iterator, Collection JavaDoc set) {
291             super(iterator);
292             this.set = set;
293         }
294
295         public Object JavaDoc next() {
296             last = iterator.next();
297             return last;
298         }
299
300         public void remove() {
301             set.remove(last);
302             iterator.remove();
303             last = null;
304         }
305     }
306
307 }
308
Popular Tags