KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > collections > collection > CompositeCollection


1 /*
2  * Copyright 2001-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.collection;
17
18 import java.lang.reflect.Array JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.Arrays JavaDoc;
21 import java.util.Collection JavaDoc;
22 import java.util.Iterator JavaDoc;
23
24 import org.apache.commons.collections.iterators.EmptyIterator;
25 import org.apache.commons.collections.iterators.IteratorChain;
26 import org.apache.commons.collections.list.UnmodifiableList;
27
28 /**
29  * Decorates a collection of other collections to provide a single unified view.
30  * <p>
31  * Changes made to this collection will actually be made on the decorated collection.
32  * Add and remove operations require the use of a pluggable strategy. If no
33  * strategy is provided then add and remove are unsupported.
34  *
35  * @since Commons Collections 3.0
36  * @version $Revision: 1.7 $ $Date: 2004/05/26 21:58:02 $
37  *
38  * @author Brian McCallister
39  * @author Stephen Colebourne
40  * @author Phil Steitz
41  */

42 public class CompositeCollection implements Collection JavaDoc {
43     
44     /** CollectionMutator to handle changes to the collection */
45     protected CollectionMutator mutator;
46     
47     /** Collections in the composite */
48     protected Collection JavaDoc[] all;
49     
50     /**
51      * Create an empty CompositeCollection.
52      */

53     public CompositeCollection() {
54         super();
55         this.all = new Collection JavaDoc[0];
56     }
57     
58     /**
59      * Create a Composite Collection with only coll composited.
60      *
61      * @param coll a collection to decorate
62      */

63     public CompositeCollection(Collection JavaDoc coll) {
64         this();
65         this.addComposited(coll);
66     }
67     
68     /**
69      * Create a CompositeCollection with colls as the initial list of
70      * composited collections.
71      *
72      * @param colls an array of collections to decorate
73      */

74     public CompositeCollection(Collection JavaDoc[] colls) {
75         this();
76         this.addComposited(colls);
77     }
78     
79     //-----------------------------------------------------------------------
80
/**
81      * Gets the size of this composite collection.
82      * <p>
83      * This implementation calls <code>size()</code> on each collection.
84      *
85      * @return total number of elements in all contained containers
86      */

87     public int size() {
88         int size = 0;
89         for (int i = this.all.length - 1; i >= 0; i--) {
90             size += this.all[i].size();
91         }
92         return size;
93     }
94     
95     /**
96      * Checks whether this composite collection is empty.
97      * <p>
98      * This implementation calls <code>isEmpty()</code> on each collection.
99      *
100      * @return true if all of the contained collections are empty
101      */

102     public boolean isEmpty() {
103         for (int i = this.all.length - 1; i >= 0; i--) {
104             if (this.all[i].isEmpty() == false) {
105                 return false;
106             }
107         }
108         return true;
109     }
110     
111     /**
112      * Checks whether this composite collection contains the object.
113      * <p>
114      * This implementation calls <code>contains()</code> on each collection.
115      *
116      * @param obj the object to search for
117      * @return true if obj is contained in any of the contained collections
118      */

119     public boolean contains(Object JavaDoc obj) {
120         for (int i = this.all.length - 1; i >= 0; i--) {
121             if (this.all[i].contains(obj)) {
122                 return true;
123             }
124         }
125         return false;
126     }
127     
128     /**
129      * Gets an iterator over all the collections in this composite.
130      * <p>
131      * This implementation uses an <code>IteratorChain</code>.
132      *
133      * @return an <code>IteratorChain</code> instance which supports
134      * <code>remove()</code>. Iteration occurs over contained collections in
135      * the order they were added, but this behavior should not be relied upon.
136      * @see IteratorChain
137      */

138     public Iterator JavaDoc iterator() {
139         if (this.all.length == 0) {
140             return EmptyIterator.INSTANCE;
141         }
142         IteratorChain chain = new IteratorChain();
143         for (int i = 0; i < this.all.length; ++i) {
144             chain.addIterator(this.all[i].iterator());
145         }
146         return chain;
147     }
148     
149     /**
150      * Returns an array containing all of the elements in this composite.
151      *
152      * @return an object array of all the elements in the collection
153      */

154     public Object JavaDoc[] toArray() {
155         final Object JavaDoc[] result = new Object JavaDoc[this.size()];
156         int i = 0;
157         for (Iterator JavaDoc it = this.iterator(); it.hasNext(); i++) {
158             result[i] = it.next();
159         }
160         return result;
161     }
162     
163     /**
164      * Returns an object array, populating the supplied array if possible.
165      * See <code>Collection</code> interface for full details.
166      *
167      * @param array the array to use, populating if possible
168      * @return an array of all the elements in the collection
169      */

170     public Object JavaDoc[] toArray(Object JavaDoc[] array) {
171         int size = this.size();
172         Object JavaDoc[] result = null;
173         if (array.length >= size) {
174             result = array;
175         }
176         else {
177             result = (Object JavaDoc[]) Array.newInstance(array.getClass().getComponentType(), size);
178         }
179         
180         int offset = 0;
181         for (int i = 0; i < this.all.length; ++i) {
182             for (Iterator JavaDoc it = this.all[i].iterator(); it.hasNext();) {
183                 result[offset++] = it.next();
184             }
185         }
186         if (result.length > size) {
187             result[size] = null;
188         }
189         return result;
190     }
191     
192     /**
193      * Adds an object to the collection, throwing UnsupportedOperationException
194      * unless a CollectionMutator strategy is specified.
195      *
196      * @param obj the object to add
197      * @return true if the collection was modified
198      * @throws UnsupportedOperationException if CollectionMutator hasn't been set
199      * @throws UnsupportedOperationException if add is unsupported
200      * @throws ClassCastException if the object cannot be added due to its type
201      * @throws NullPointerException if the object cannot be added because its null
202      * @throws IllegalArgumentException if the object cannot be added
203      */

204     public boolean add(Object JavaDoc obj) {
205         if (this.mutator == null) {
206            throw new UnsupportedOperationException JavaDoc(
207            "add() is not supported on CompositeCollection without a CollectionMutator strategy");
208         }
209         return this.mutator.add(this, this.all, obj);
210     }
211     
212     /**
213      * Removes an object from the collection, throwing UnsupportedOperationException
214      * unless a CollectionMutator strategy is specified.
215      *
216      * @param obj the object being removed
217      * @return true if the collection is changed
218      * @throws UnsupportedOperationException if removed is unsupported
219      * @throws ClassCastException if the object cannot be removed due to its type
220      * @throws NullPointerException if the object cannot be removed because its null
221      * @throws IllegalArgumentException if the object cannot be removed
222      */

223     public boolean remove(Object JavaDoc obj) {
224         if (this.mutator == null) {
225             throw new UnsupportedOperationException JavaDoc(
226             "remove() is not supported on CompositeCollection without a CollectionMutator strategy");
227         }
228         return this.mutator.remove(this, this.all, obj);
229     }
230     
231     /**
232      * Checks whether this composite contains all the elements in the specified collection.
233      * <p>
234      * This implementation calls <code>contains()</code> for each element in the
235      * specified collection.
236      *
237      * @param coll the collection to check for
238      * @return true if all elements contained
239      */

240     public boolean containsAll(Collection JavaDoc coll) {
241         for (Iterator JavaDoc it = coll.iterator(); it.hasNext();) {
242             if (this.contains(it.next()) == false) {
243                 return false;
244             }
245         }
246         return true;
247     }
248     
249     /**
250      * Adds a collection of elements to this collection, throwing
251      * UnsupportedOperationException unless a CollectionMutator strategy is specified.
252      *
253      * @param coll the collection to add
254      * @return true if the collection was modified
255      * @throws UnsupportedOperationException if CollectionMutator hasn't been set
256      * @throws UnsupportedOperationException if add is unsupported
257      * @throws ClassCastException if the object cannot be added due to its type
258      * @throws NullPointerException if the object cannot be added because its null
259      * @throws IllegalArgumentException if the object cannot be added
260      */

261     public boolean addAll(Collection JavaDoc coll) {
262         if (this.mutator == null) {
263             throw new UnsupportedOperationException JavaDoc(
264             "addAll() is not supported on CompositeCollection without a CollectionMutator strategy");
265         }
266         return this.mutator.addAll(this, this.all, coll);
267     }
268     
269     /**
270      * Removes the elements in the specified collection from this composite collection.
271      * <p>
272      * This implementation calls <code>removeAll</code> on each collection.
273      *
274      * @param coll the collection to remove
275      * @return true if the collection was modified
276      * @throws UnsupportedOperationException if removeAll is unsupported
277      */

278     public boolean removeAll(Collection JavaDoc coll) {
279         if (coll.size() == 0) {
280             return false;
281         }
282         boolean changed = false;
283         for (int i = this.all.length - 1; i >= 0; i--) {
284             changed = (this.all[i].removeAll(coll) || changed);
285         }
286         return changed;
287     }
288     
289     /**
290      * Retains all the elements in the specified collection in this composite collection,
291      * removing all others.
292      * <p>
293      * This implementation calls <code>retainAll()</code> on each collection.
294      *
295      * @param coll the collection to remove
296      * @return true if the collection was modified
297      * @throws UnsupportedOperationException if retainAll is unsupported
298      */

299     public boolean retainAll(final Collection JavaDoc coll) {
300         boolean changed = false;
301         for (int i = this.all.length - 1; i >= 0; i--) {
302             changed = (this.all[i].retainAll(coll) || changed);
303         }
304         return changed;
305     }
306     
307     /**
308      * Removes all of the elements from this collection .
309      * <p>
310      * This implementation calls <code>clear()</code> on each collection.
311      *
312      * @throws UnsupportedOperationException if clear is unsupported
313      */

314     public void clear() {
315         for (int i = 0; i < this.all.length; ++i) {
316             this.all[i].clear();
317         }
318     }
319     
320     //-----------------------------------------------------------------------
321
/**
322      * Specify a CollectionMutator strategy instance to handle changes.
323      *
324      * @param mutator the mutator to use
325      */

326     public void setMutator(CollectionMutator mutator) {
327         this.mutator = mutator;
328     }
329     
330     /**
331      * Add these Collections to the list of collections in this composite
332      *
333      * @param comps Collections to be appended to the composite
334      */

335     public void addComposited(Collection JavaDoc[] comps) {
336         ArrayList JavaDoc list = new ArrayList JavaDoc(Arrays.asList(this.all));
337         list.addAll(Arrays.asList(comps));
338         all = (Collection JavaDoc[]) list.toArray(new Collection JavaDoc[list.size()]);
339     }
340     
341     /**
342      * Add an additional collection to this composite.
343      *
344      * @param c the collection to add
345      */

346     public void addComposited(Collection JavaDoc c) {
347         this.addComposited(new Collection JavaDoc[]{c});
348     }
349     
350     /**
351      * Add two additional collections to this composite.
352      *
353      * @param c the first collection to add
354      * @param d the second collection to add
355      */

356     public void addComposited(Collection JavaDoc c, Collection JavaDoc d) {
357         this.addComposited(new Collection JavaDoc[]{c, d});
358     }
359     
360     /**
361      * Removes a collection from the those being decorated in this composite.
362      *
363      * @param coll collection to be removed
364      */

365     public void removeComposited(Collection JavaDoc coll) {
366         ArrayList JavaDoc list = new ArrayList JavaDoc(this.all.length);
367         list.addAll(Arrays.asList(this.all));
368         list.remove(coll);
369         this.all = (Collection JavaDoc[]) list.toArray(new Collection JavaDoc[list.size()]);
370     }
371     
372     /**
373      * Returns a new collection containing all of the elements
374      *
375      * @return A new ArrayList containing all of the elements in this composite.
376      * The new collection is <i>not</i> backed by this composite.
377      */

378     public Collection JavaDoc toCollection() {
379         return new ArrayList JavaDoc(this);
380     }
381     
382     /**
383      * Gets the collections being decorated.
384      *
385      * @return Unmodifiable collection of all collections in this composite.
386      */

387     public Collection JavaDoc getCollections() {
388         return UnmodifiableList.decorate(Arrays.asList(this.all));
389     }
390     
391     //-----------------------------------------------------------------------
392
/**
393      * Pluggable strategy to handle changes to the composite.
394      */

395     public interface CollectionMutator {
396         
397         /**
398          * Called when an object is to be added to the composite.
399          *
400          * @param composite the CompositeCollection being changed
401          * @param collections all of the Collection instances in this CompositeCollection
402          * @param obj the object being added
403          * @return true if the collection is changed
404          * @throws UnsupportedOperationException if add is unsupported
405          * @throws ClassCastException if the object cannot be added due to its type
406          * @throws NullPointerException if the object cannot be added because its null
407          * @throws IllegalArgumentException if the object cannot be added
408          */

409         public boolean add(CompositeCollection composite, Collection JavaDoc[] collections, Object JavaDoc obj);
410         
411         /**
412          * Called when a collection is to be added to the composite.
413          *
414          * @param composite the CompositeCollection being changed
415          * @param collections all of the Collection instances in this CompositeCollection
416          * @param coll the collection being added
417          * @return true if the collection is changed
418          * @throws UnsupportedOperationException if add is unsupported
419          * @throws ClassCastException if the object cannot be added due to its type
420          * @throws NullPointerException if the object cannot be added because its null
421          * @throws IllegalArgumentException if the object cannot be added
422          */

423         public boolean addAll(CompositeCollection composite, Collection JavaDoc[] collections, Collection JavaDoc coll);
424         
425         /**
426          * Called when an object is to be removed to the composite.
427          *
428          * @param composite the CompositeCollection being changed
429          * @param collections all of the Collection instances in this CompositeCollection
430          * @param obj the object being removed
431          * @return true if the collection is changed
432          * @throws UnsupportedOperationException if removed is unsupported
433          * @throws ClassCastException if the object cannot be removed due to its type
434          * @throws NullPointerException if the object cannot be removed because its null
435          * @throws IllegalArgumentException if the object cannot be removed
436          */

437         public boolean remove(CompositeCollection composite, Collection JavaDoc[] collections, Object JavaDoc obj);
438         
439     }
440     
441 }
442
443
Popular Tags