001    /*
002            Copyright (c) 2009 Olivier Chafik, All Rights Reserved
003            
004            This file is part of JNAerator (http://jnaerator.googlecode.com/).
005            
006            JNAerator is free software: you can redistribute it and/or modify
007            it under the terms of the GNU General Public License as published by
008            the Free Software Foundation, either version 3 of the License, or
009            (at your option) any later version.
010            
011            JNAerator is distributed in the hope that it will be useful,
012            but WITHOUT ANY WARRANTY; without even the implied warranty of
013            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014            GNU General Public License for more details.
015            
016            You should have received a copy of the GNU General Public License
017            along with JNAerator.  If not, see <http://www.gnu.org/licenses/>.
018    */
019    package com.ochafik.util;
020    import java.lang.reflect.Array;
021    import java.util.ArrayList;
022    import java.util.Arrays;
023    import java.util.Collection;
024    import java.util.Iterator;
025    import java.util.LinkedList;
026    import java.util.Vector;
027    
028    /*
029     * This is a Collection that gathers the content of several collections, without the need to create
030     *  a big structure and add them all to it. It is space and speed efficient (except for containsAll(Collection)),
031     *  however it does not implement add(U) and addAll(Collection<U>) optional methods. 
032     *  
033     * It should be use in cases where you want to iterate through several collections as through one.
034     */
035    public class CompoundCollection<U> implements Collection<U> {
036            Collection<Collection<? extends U> > collections;
037            public CompoundCollection() {
038                    collections=new LinkedList<Collection<? extends U> >();
039            }
040            public CompoundCollection(Collection<Collection<? extends U>> lists) {
041                    collections = new ArrayList<Collection<? extends U>>(lists);
042            }
043            public CompoundCollection(Collection<? extends U>... lists) {
044                    this(Arrays.asList(lists));
045            }
046            public void addComponent(Collection<U> col) {
047            collections.add(col);
048        }
049        public boolean removeComponent(Collection<U> col) {
050            return collections.remove(col);
051        }
052        public int size() {
053                    int s=0;
054                    for (Collection<? extends U> col : collections) {
055                            s+=col.size();
056                    }
057                    return s;
058            }
059            public void clearComponents() {
060                    collections.clear();
061            }
062            public void clear() {
063                    for (Collection<? extends U> col : collections) {
064                            col.clear();
065                    }
066            }
067            public boolean isEmpty() {
068                    for (Collection<? extends U> col : collections) {
069                            if (!col.isEmpty()) {
070                                    return false; 
071                            }
072                    }
073                    return true;
074            }
075            public Object[] toArray() {
076                    int len=size();
077                    Object[] a=new Object[len];
078                    int i=0;
079                    for (U element : this) {
080                            a[i]=element;
081                    }
082                    return a;
083            }
084        @SuppressWarnings("unchecked")
085        //@Deprecated
086        public <T> T[] toArray(T[] objects) {
087            int size=size();
088            Class<T> clazz=(Class<T>)objects.getClass().getComponentType();
089            T[] array=(T[])Array.newInstance(clazz,size);
090            int i=0;
091            for (Object element : this) {
092                array[i]=clazz.cast(element);
093            }
094            return array;
095            }
096        @Deprecated
097            public boolean add(U object) { 
098            throw new UnsupportedOperationException(); 
099        }    
100            public boolean contains(Object object) {
101                    for (Collection<? extends U> col : collections) {
102                            if (col.contains(object)) {
103                                    return true; 
104                            }
105                    }
106                    return false;
107            }
108            public boolean remove(Object object) {
109            boolean changed=false;
110                    for (Collection<? extends U> col : collections) {
111                            if (col.remove(object)) {
112                    changed=true;
113                                    //return true; 
114                            }
115                    }
116            return changed;
117                    //return false;
118            }
119        @Deprecated
120        public boolean addAll(Collection<? extends U> col) {
121            boolean changed=false;
122            for (U u : col) {
123                changed=add(u) || changed;
124            } 
125            return changed;
126            }
127        public boolean containsAll(Collection<?> col) {
128            for (Object o : col) {
129                if (!contains(o)) {
130                    return false;
131                }
132            }
133            return true; 
134            }
135        public boolean removeAll(Collection<?> col) {
136            boolean changed=false;
137            for (Object o : col) {
138                changed=remove(o) || changed;
139            } 
140            return changed;
141            }
142        public boolean retainAll(Collection<?> col) {
143            boolean changed=false;
144            for (Iterator<U> it=iterator();it.hasNext();) {
145                if (!col.contains(it.next())) {
146                    it.remove();
147                    changed=true;
148                }
149            }
150            return changed; 
151            }
152            public Iterator<U> iterator() {
153                    //final Iterator firstIterator=first.iterator(),restIterator=rest.iterator();
154                    return new Iterator<U>() {
155                            Iterator<? extends Collection<? extends U>> collectionsIterator=collections.iterator();
156                            Iterator<? extends U> currentCollectionIterator=
157                                    collectionsIterator.hasNext() ?
158                                            collectionsIterator.next().iterator() :
159                                            new Vector<U>(0).iterator();
160                            public boolean hasNext() {
161                                    boolean collectionExhausted=false;
162                                    do {
163                                            collectionExhausted=true;
164                                            if (currentCollectionIterator.hasNext()) {
165                                                    return true;
166                                            } else if (collectionsIterator.hasNext()) {
167                                                    currentCollectionIterator=collectionsIterator.next().iterator();
168                                                    collectionExhausted=false;
169                                            } 
170                                    } while (!collectionExhausted);
171                                    return false;
172                            }
173                            public U next() {
174                                    boolean collectionExhausted=false;
175                                    do {
176                                            collectionExhausted=true;
177                                            if (currentCollectionIterator.hasNext()) {
178                                                    return currentCollectionIterator.next();
179                                            } else {
180                                                    currentCollectionIterator=collectionsIterator.next().iterator();
181                                                    collectionExhausted=false;
182                                            }
183                                    } while (!collectionExhausted);
184                                    return null;
185                            }
186                            public void remove() {
187                                    currentCollectionIterator.remove();
188                            }    
189                    };
190            }
191    }