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 }