001 package jigcell.compare.data;
002
003 import java.beans.DefaultPersistenceDelegate;
004 import java.beans.Encoder;
005 import java.beans.Expression;
006 import java.beans.Statement;
007 import java.util.ArrayList;
008 import java.util.Collection;
009 import java.util.Collections;
010 import java.util.Comparator;
011 import java.util.HashMap;
012 import java.util.Iterator;
013 import java.util.List;
014 import java.util.ListIterator;
015 import java.util.Map;
016 import jigcell.compare.IDataGenerator;
017 import jigcell.compare.impl.Compare;
018
019 /**
020 * Manages a list of data generators. This class is unsynchronized and must be protected from concurrent access.
021 *
022 * <p>
023 * This code is licensed under the DARPA BioCOMP Open Source License. See LICENSE for more details.
024 * </p>
025 *
026 * @author Nicholas Allen
027 */
028
029 public class DataGeneratorList implements Cloneable, IDataGeneratorList {
030
031 /**
032 * Whether indexing is currently being used
033 */
034
035 protected boolean indexed;
036
037 /**
038 * Internal List[IDataGenerator] implementation
039 */
040
041 protected List list;
042
043 /**
044 * Map[String,IDataGenerator] from generator id keys to generators
045 */
046
047 protected transient Map idToGenerator;
048
049 /**
050 * Map[String,IDataGenerator] from generator names to generators
051 */
052
053 protected transient Map nameToGenerator;
054
055 /**
056 * Persists the list by using a series of add statements.
057 */
058
059 protected static class DataGeneratorListDelegate extends DefaultPersistenceDelegate {
060 protected Expression instantiate (Object o, Encoder encoder) {
061 return new Expression (o, o.getClass (), "new", new Object [] {new Integer (((DataGeneratorList) o).size ())});
062 }
063
064 protected void initialize (Class clazz, Object o1, Object o2, Encoder encoder) {
065 super.initialize (clazz, o1, o2, encoder);
066 for (Iterator iterator = ((DataGeneratorList) o1).iterator (); iterator.hasNext (); )
067 encoder.writeStatement (new Statement (o1, "add", new Object [] {iterator.next ()}));
068 }
069 }
070
071 static {
072 Compare.addDelegate (DataGeneratorList.class, new DataGeneratorListDelegate ());
073 }
074
075 /**
076 * Converts a collection to a list of data generators. If the input is already the correct type, it may be returned unchanged.
077 *
078 * @param collection Collection
079 */
080
081 public static IDataGeneratorList createList (Object collection) {
082 if (collection == null)
083 throw new IllegalArgumentException ();
084 if (collection instanceof IDataGeneratorList)
085 return (IDataGeneratorList) collection;
086 IDataGeneratorList list = new DataGeneratorList ();
087 list.addAll ((Collection) collection);
088 return list;
089 }
090
091 /**
092 * Creates a new list of data generators.
093 */
094
095 public DataGeneratorList () {
096 this (10);
097 }
098
099 /**
100 * Creates a new list of data generators.
101 *
102 * @param initialCapacity Initial list capacity
103 */
104
105 public DataGeneratorList (int initialCapacity) {
106 list = new ArrayList (initialCapacity);
107 }
108
109 /**
110 * Copies an existing list of data generators. If the existing list is a DataGeneratorList that has been indexed, the new list will be
111 * indexed as well.
112 */
113
114 public DataGeneratorList (IDataGeneratorList generators) {
115 if (generators == null)
116 throw new IllegalArgumentException ();
117 if (generators instanceof DataGeneratorList) {
118 DataGeneratorList generatorsImpl = (DataGeneratorList) generators;
119 list = new ArrayList (generatorsImpl.list);
120 indexed = generatorsImpl.indexed;
121 if (indexed) {
122 idToGenerator = new HashMap (generatorsImpl.idToGenerator);
123 nameToGenerator = new HashMap (generatorsImpl.nameToGenerator);
124 }
125 return;
126 }
127 list = new ArrayList (generators.asList ());
128 }
129
130 /**
131 * {@inheritDoc}
132 */
133
134 public void add (int index, IDataGenerator generator) {
135 if (generator == null)
136 throw new IllegalArgumentException ();
137 list.add (index, generator);
138 index (generator);
139 }
140
141 /**
142 * {@inheritDoc}
143 */
144
145 public void add (IDataGenerator generator) {
146 if (generator == null)
147 throw new IllegalArgumentException ();
148 list.add (generator);
149 index (generator);
150 }
151
152 /**
153 * {@inheritDoc}
154 */
155
156 public void addAll (Collection collection) {
157 if (collection == null)
158 throw new IllegalArgumentException ();
159 for (Iterator iterator = collection.iterator (); iterator.hasNext (); )
160 add ((IDataGenerator) iterator.next ());
161 }
162
163 /**
164 * {@inheritDoc}
165 */
166
167 public void addAll (IDataGeneratorList generatorList) {
168 if (generatorList == null)
169 throw new IllegalArgumentException ();
170 addAll (generatorList.asList ());
171 }
172
173 /**
174 * {@inheritDoc}
175 */
176
177 public List asList () {
178 return list;
179 }
180
181 /**
182 * {@inheritDoc}
183 */
184
185 public void clear () {
186 list.clear ();
187 if (indexed) {
188 idToGenerator.clear ();
189 nameToGenerator.clear ();
190 }
191 }
192
193 public Object clone () {
194 return new DataGeneratorList (this);
195 }
196
197 /**
198 * {@inheritDoc}
199 */
200
201 public void createIndex () {
202 idToGenerator = new HashMap ();
203 nameToGenerator = new HashMap ();
204 IDataGenerator generator;
205 for (int i = 0, l = size (); i < l; i++) {
206 generator = (IDataGenerator) get (i);
207 idToGenerator.put (generator.getAttribute (IDataGenerator.ATTRIBUTE_GUID), generator);
208 nameToGenerator.put (generator.getName (), generator);
209 }
210 indexed = true;
211 }
212
213 /**
214 * {@inheritDoc}
215 */
216
217 public void flushIndex () {
218 idToGenerator = nameToGenerator = null;
219 indexed = false;
220 }
221
222 /**
223 * {@inheritDoc}
224 */
225
226 public IDataGenerator get (int index) {
227 return (IDataGenerator) list.get (index);
228 }
229
230 /**
231 * {@inheritDoc}
232 */
233
234 public IDataGenerator get (Key key) {
235 if (key == null)
236 return null;
237 String value = key.getId ();
238 if (value == null)
239 return get (key.getName ());
240 if (indexed) {
241 IDataGenerator generator = (IDataGenerator) idToGenerator.get (value);
242 if (generator != null)
243 return generator;
244 }
245 for (int i = 0, l = size (); i < l; i++) {
246 IDataGenerator generator = get (i);
247 if (value.equals (generator.getAttribute (IDataGenerator.ATTRIBUTE_GUID)))
248 return generator;
249 }
250 return get (key.getName ());
251 }
252
253 /**
254 * {@inheritDoc}
255 */
256
257 public IDataGenerator get (String name) {
258 if (name == null)
259 return null;
260 if (indexed) {
261 IDataGenerator generator = (IDataGenerator) nameToGenerator.get (name);
262 if (generator != null)
263 return generator;
264 }
265 for (int i = 0, l = size (); i < l; i++) {
266 IDataGenerator generator = get (i);
267 if (name.equals (generator.getName ()))
268 return generator;
269 }
270 return null;
271 }
272
273 /**
274 * {@inheritDoc}
275 */
276
277 public int indexOf (IDataGenerator generator) {
278 if (generator == null)
279 throw new IllegalArgumentException ();
280 return list.indexOf (generator);
281 }
282
283 /**
284 * {@inheritDoc}
285 */
286
287 public boolean isEmpty () {
288 return list.isEmpty ();
289 }
290
291 /**
292 * {@inheritDoc}
293 */
294
295 public ListIterator iterator () {
296 return list.listIterator ();
297 }
298
299 /**
300 * {@inheritDoc}
301 */
302
303 public ListIterator iterator (int index) {
304 return list.listIterator (index);
305 }
306
307 /**
308 * {@inheritDoc}
309 */
310
311 public IDataGenerator remove (int index) {
312 IDataGenerator generator = (IDataGenerator) list.remove (index);
313 unindex (generator);
314 return generator;
315 }
316
317 /**
318 * {@inheritDoc}
319 */
320
321 public IDataGenerator set (int index, IDataGenerator generator) {
322 if (generator == null)
323 throw new IllegalArgumentException ();
324 IDataGenerator oldGenerator = (IDataGenerator) list.set (index, generator);
325 index (generator);
326 unindex (oldGenerator);
327 return oldGenerator;
328 }
329
330 /**
331 * {@inheritDoc}
332 */
333
334 public int size () {
335 return list.size ();
336 }
337
338 /**
339 * {@inheritDoc}
340 */
341
342 public void sort (Comparator comparator) {
343 Collections.sort (list, comparator);
344 }
345
346 /**
347 * {@inheritDoc}
348 */
349
350 public IDataGenerator [] toArray () {
351 return (IDataGenerator []) list.toArray (new IDataGenerator [0]);
352 }
353
354 public String toString () {
355 return list.toString ();
356 }
357
358 /**
359 * Adds a generator to the index.
360 *
361 * @param generator Generator
362 */
363
364 private void index (IDataGenerator generator) {
365 if (!indexed)
366 return;
367 idToGenerator.put (generator.getAttribute (IDataGenerator.ATTRIBUTE_GUID), generator);
368 nameToGenerator.put (generator.getName (), generator);
369 }
370
371 /**
372 * Removes a generator from the index.
373 *
374 * @param generator Generator
375 */
376
377 private void unindex (IDataGenerator generator) {
378 if (!indexed)
379 return;
380 idToGenerator.remove (generator.getAttribute (IDataGenerator.ATTRIBUTE_GUID));
381 nameToGenerator.remove (generator.getName ());
382 }
383 }