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    }