001/*
002 * Copyright 2010-2015 Institut Pasteur.
003 * 
004 * This file is part of Icy.
005 * 
006 * Icy 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 * Icy 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 Icy. If not, see <http://www.gnu.org/licenses/>.
018 */
019package icy.swimmingPool;
020
021import icy.util.StringUtil;
022
023import java.util.ArrayList;
024import java.util.Collection;
025
026import javax.swing.event.EventListenerList;
027
028public class SwimmingPool
029{
030    private final ArrayList<SwimmingObject> objects;
031    private final EventListenerList listeners;
032
033    public SwimmingPool()
034    {
035        objects = new ArrayList<SwimmingObject>();
036        listeners = new EventListenerList();
037    }
038
039    public void add(SwimmingObject object)
040    {
041        if (object != null)
042        {
043            synchronized (objects)
044            {
045                objects.add(object);
046            }
047
048            fireSwimmingPoolEvent(new SwimmingPoolEvent(SwimmingPoolEventType.ELEMENT_ADDED, object));
049        }
050    }
051
052    public void remove(SwimmingObject object)
053    {
054        final boolean b;
055
056        synchronized (objects)
057        {
058            b = objects.remove(object);
059        }
060
061        if (b)
062            fireSwimmingPoolEvent(new SwimmingPoolEvent(SwimmingPoolEventType.ELEMENT_REMOVED, object));
063    }
064
065    public void removeAll()
066    {
067        final boolean b;
068
069        synchronized (objects)
070        {
071            b = !objects.isEmpty();
072
073            if (b)
074                objects.clear();
075        }
076
077        if (b)
078            fireSwimmingPoolEvent(new SwimmingPoolEvent(SwimmingPoolEventType.ELEMENT_REMOVED, null));
079    }
080
081    /**
082     * Remove all objects contained in the collection from the swimming pool.
083     */
084    public void removeAll(Collection<SwimmingObject> sos)
085    {
086        final boolean b;
087
088        synchronized (objects)
089        {
090            b = objects.removeAll(sos);
091        }
092
093        if (b)
094            fireSwimmingPoolEvent(new SwimmingPoolEvent(SwimmingPoolEventType.ELEMENT_REMOVED, null));
095    }
096
097    /**
098     * Remove all object with specified name (or name starting with specified name).
099     */
100    public void removeAll(String name, boolean startWith)
101    {
102        boolean b = false;
103
104        synchronized (objects)
105        {
106            for (int i = objects.size() - 1; i >= 0; i--)
107            {
108                final SwimmingObject so = objects.get(i);
109
110                if (so != null)
111                {
112                    if (startWith)
113                    {
114                        if (so.getName().startsWith(name))
115                        {
116                            objects.remove(i);
117                            b = true;
118                        }
119                    }
120                    else if (StringUtil.equals(name, so.getName()))
121                    {
122                        objects.remove(i);
123                        b = true;
124                    }
125                }
126            }
127        }
128
129        if (b)
130            fireSwimmingPoolEvent(new SwimmingPoolEvent(SwimmingPoolEventType.ELEMENT_REMOVED, null));
131    }
132
133    /**
134     * Remove all object of specified class type
135     */
136    public void removeAll(Class<?> objectType)
137    {
138        boolean b = false;
139
140        synchronized (objects)
141        {
142            for (int i = objects.size() - 1; i >= 0; i--)
143            {
144                final SwimmingObject so = objects.get(i);
145
146                if (so != null)
147                {
148                    final Object obj = so.getObject();
149
150                    if ((obj != null) && objectType.isInstance(obj))
151                    {
152                        objects.remove(i);
153                        b = true;
154                    }
155                }
156            }
157        }
158
159        if (b)
160            fireSwimmingPoolEvent(new SwimmingPoolEvent(SwimmingPoolEventType.ELEMENT_REMOVED, null));
161    }
162
163    /**
164     * Return all objects of the swimming pool
165     */
166    public ArrayList<SwimmingObject> getObjects()
167    {
168        return new ArrayList<SwimmingObject>(objects);
169    }
170
171    /**
172     * Return objects with specified name (or name starting with specified name).
173     */
174    public ArrayList<SwimmingObject> getObjects(String name, boolean startWith)
175    {
176        final ArrayList<SwimmingObject> result = new ArrayList<SwimmingObject>();
177
178        synchronized (objects)
179        {
180            for (SwimmingObject so : objects)
181            {
182                if (so != null)
183                {
184                    if (startWith)
185                    {
186                        if (so.getName().startsWith(name))
187                            result.add(so);
188                    }
189                    else if (StringUtil.equals(name, so.getName()))
190                        result.add(so);
191                }
192            }
193        }
194
195        return result;
196    }
197
198    /**
199     * Return objects of specified class type
200     */
201    public ArrayList<SwimmingObject> getObjects(Class<?> objectType)
202    {
203        final ArrayList<SwimmingObject> result = new ArrayList<SwimmingObject>();
204
205        synchronized (objects)
206        {
207            for (SwimmingObject so : objects)
208            {
209                if (so != null)
210                {
211                    final Object obj = so.getObject();
212
213                    if ((obj != null) && objectType.isInstance(obj))
214                        result.add(so);
215                }
216            }
217        }
218
219        return result;
220    }
221
222    /**
223     * Return and remove objects with specified name (or name starting with specified name).
224     */
225    public ArrayList<SwimmingObject> popObjects(String name, boolean startWith)
226    {
227        final ArrayList<SwimmingObject> result = new ArrayList<SwimmingObject>();
228
229        synchronized (objects)
230        {
231            for (int i = objects.size() - 1; i >= 0; i--)
232            {
233                final SwimmingObject so = objects.get(i);
234
235                if (so != null)
236                {
237                    if (startWith)
238                    {
239                        if (so.getName().startsWith(name))
240                        {
241                            result.add(so);
242                            objects.remove(i);
243                        }
244                    }
245                    else if (StringUtil.equals(name, so.getName()))
246                    {
247                        result.add(so);
248                        objects.remove(i);
249                    }
250                }
251            }
252        }
253
254        return result;
255    }
256
257    /**
258     * Return and remove objects of specified class type
259     */
260    public ArrayList<SwimmingObject> popObjects(Class<?> objectType)
261    {
262        final ArrayList<SwimmingObject> result = new ArrayList<SwimmingObject>();
263
264        synchronized (objects)
265        {
266            for (int i = objects.size() - 1; i >= 0; i--)
267            {
268                final SwimmingObject so = objects.get(i);
269
270                if (so != null)
271                {
272                    final Object obj = so.getObject();
273
274                    if ((obj != null) && objectType.isInstance(obj))
275                    {
276                        result.add(so);
277                        objects.remove(i);
278                    }
279                }
280            }
281        }
282
283        return result;
284    }
285
286    /**
287     * Return true if the swimming pool contains at least one object with the specified name (or
288     * name starting with specified name).
289     */
290    public boolean hasObjects(String name, boolean startWith)
291    {
292        synchronized (objects)
293        {
294            for (SwimmingObject so : objects)
295            {
296                if (so != null)
297                {
298                    if (startWith)
299                    {
300                        if (so.getName().startsWith(name))
301                            return true;
302                    }
303                    else if (StringUtil.equals(name, so.getName()))
304                        return true;
305                }
306            }
307        }
308
309        return false;
310    }
311
312    /**
313     * Return true if the swimming pool contains at least one object with the specified class type.
314     */
315    public boolean hasObjects(Class<?> objectType)
316    {
317        synchronized (objects)
318        {
319            for (SwimmingObject so : objects)
320            {
321                if (so != null)
322                {
323                    final Object obj = so.getObject();
324
325                    if ((obj != null) && objectType.isInstance(obj))
326                        return true;
327                }
328            }
329        }
330
331        return false;
332    }
333
334    /**
335     * Return the number of object with the specified name (or name starting with specified name)
336     * contained in the swimming pool.
337     */
338    public int getCount(String name, boolean startWith)
339    {
340        int result = 0;
341
342        synchronized (objects)
343        {
344            for (SwimmingObject so : objects)
345            {
346                if (so != null)
347                {
348                    if (startWith)
349                    {
350                        if (so.getName().startsWith(name))
351                            result++;
352                    }
353                    else if (StringUtil.equals(name, so.getName()))
354                        result++;
355                }
356            }
357        }
358
359        return result;
360    }
361
362    /**
363     * Return the number of object with the specified class type contained in the swimming pool.
364     */
365    public int getCount(Class<?> objectType)
366    {
367        int result = 0;
368
369        synchronized (objects)
370        {
371            for (SwimmingObject so : objects)
372            {
373                if (so != null)
374                {
375                    final Object obj = so.getObject();
376
377                    if ((obj != null) && objectType.isInstance(obj))
378                        result++;
379                }
380            }
381        }
382
383        return result;
384    }
385
386    public void addListener(SwimmingPoolListener listener)
387    {
388        listeners.add(SwimmingPoolListener.class, listener);
389    }
390
391    public void removeListener(SwimmingPoolListener listener)
392    {
393        listeners.remove(SwimmingPoolListener.class, listener);
394    }
395
396    private void fireSwimmingPoolEvent(SwimmingPoolEvent swimmingPoolEvent)
397    {
398        for (SwimmingPoolListener listener : listeners.getListeners(SwimmingPoolListener.class))
399            listener.swimmingPoolChangeEvent(swimmingPoolEvent);
400    }
401
402}