001/*******************************************************************************
002 * Copyright (c) 2014 Opt4J
003 *
004 * Permission is hereby granted, free of charge, to any person obtaining a copy
005 * of this software and associated documentation files (the "Software"), to deal
006 * in the Software without restriction, including without limitation the rights
007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008 * copies of the Software, and to permit persons to whom the Software is
009 * furnished to do so, subject to the following conditions:
010 *
011 * The above copyright notice and this permission notice shall be included in
012 * all copies or substantial portions of the Software.
013 *
014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
020 * SOFTWARE.
021 *******************************************************************************/
022
023package org.opt4j.core;
024
025import java.util.Arrays;
026import java.util.Collection;
027import java.util.Iterator;
028import java.util.LinkedHashSet;
029import java.util.Set;
030import java.util.concurrent.CopyOnWriteArraySet;
031
032/**
033 * The {@link IndividualSet} is a {@link Set} of {@link Individual}s. It allows
034 * to add and remove listeners, see {@link IndividualSetListener}.
035 * 
036 * @see org.opt4j.core.optimizer.Archive
037 * @see org.opt4j.core.optimizer.Population
038 * @author lukasiewycz
039 * 
040 */
041public class IndividualSet implements Set<Individual> {
042
043        protected final Set<Individual> individuals = new LinkedHashSet<>();
044
045        protected final Set<IndividualSetListener> listeners = new CopyOnWriteArraySet<>();
046
047        /*
048         * (non-Javadoc)
049         * 
050         * @see java.util.Collection#add(java.lang.Object)
051         */
052        @Override
053        public boolean add(Individual individual) {
054                boolean b = false;
055                if (!individuals.contains(individual)) {
056                        b = individuals.add(individual);
057                }
058                if (b) {
059                        for (IndividualSetListener listener : listeners) {
060                                listener.individualAdded(this, individual);
061                        }
062                }
063                return b;
064        }
065
066        /*
067         * (non-Javadoc)
068         * 
069         * @see java.util.Collection#iterator()
070         */
071        @Override
072        public Iterator<Individual> iterator() {
073                final Iterator<Individual> iterator = individuals.iterator();
074
075                return new Iterator<Individual>() {
076
077                        Individual current = null;
078
079                        @Override
080                        public boolean hasNext() {
081                                return iterator.hasNext();
082                        }
083
084                        @Override
085                        public Individual next() {
086                                current = iterator.next();
087                                return current;
088                        }
089
090                        @Override
091                        public void remove() {
092                                iterator.remove();
093                                if (current != null) {
094                                        for (IndividualSetListener listener : listeners) {
095                                                listener.individualRemoved(IndividualSet.this, current);
096                                        }
097                                }
098                        }
099                };
100
101        }
102
103        /*
104         * (non-Javadoc)
105         * 
106         * @see java.util.Collection#size()
107         */
108        @Override
109        public int size() {
110                return individuals.size();
111        }
112
113        /**
114         * Adds a listener.
115         * 
116         * @see #removeListener
117         * @param listener
118         *            the added listener
119         */
120        public void addListener(IndividualSetListener listener) {
121                listeners.add(listener);
122        }
123
124        /**
125         * Removes a listener.
126         * 
127         * @see #addListener
128         * @param listener
129         *            the removed listener
130         */
131        public void removeListener(IndividualSetListener listener) {
132                listeners.remove(listener);
133        }
134
135        /*
136         * (non-Javadoc)
137         * 
138         * @see java.util.Collection#clear()
139         */
140        @Override
141        public void clear() {
142                Iterator<Individual> it = iterator();
143                while (it.hasNext()) {
144                        it.next();
145                        it.remove();
146                }
147        }
148
149        /*
150         * (non-Javadoc)
151         * 
152         * @see java.util.Collection#addAll(java.util.Collection)
153         */
154        @Override
155        public boolean addAll(Collection<? extends Individual> c) {
156                boolean res = false;
157                for (Individual individual : c) {
158                        res |= add(individual);
159                }
160                return res;
161        }
162
163        /**
164         * Add all {@link Individual}s.
165         * 
166         * @param c
167         *            the individuals to be added
168         * @return true if at least one individual was added
169         */
170        public boolean addAll(Individual... c) {
171                return addAll(Arrays.asList(c));
172        }
173
174        /*
175         * (non-Javadoc)
176         * 
177         * @see java.util.Collection#contains(java.lang.Object)
178         */
179        @Override
180        public boolean contains(Object o) {
181                return individuals.contains(o);
182        }
183
184        /*
185         * (non-Javadoc)
186         * 
187         * @see java.util.Collection#containsAll(java.util.Collection)
188         */
189        @Override
190        public boolean containsAll(Collection<?> c) {
191                return individuals.containsAll(c);
192        }
193
194        /*
195         * (non-Javadoc)
196         * 
197         * @see java.util.Collection#isEmpty()
198         */
199        @Override
200        public boolean isEmpty() {
201                return individuals.isEmpty();
202        }
203
204        /*
205         * (non-Javadoc)
206         * 
207         * @see java.util.Collection#remove(java.lang.Object)
208         */
209        @Override
210        public boolean remove(Object o) {
211                boolean value = individuals.remove(o);
212                if (value) {
213                        for (IndividualSetListener listener : listeners) {
214                                listener.individualRemoved(this, (Individual) o);
215                        }
216                }
217                return value;
218        }
219
220        /*
221         * (non-Javadoc)
222         * 
223         * @see java.util.Collection#removeAll(java.util.Collection)
224         */
225        @Override
226        public boolean removeAll(Collection<?> c) {
227                boolean res = false;
228                Iterator<Individual> it = iterator();
229                while (it.hasNext()) {
230                        if (c.contains(it.next())) {
231                                it.remove();
232                                res = true;
233                        }
234                }
235                return res;
236        }
237
238        /*
239         * (non-Javadoc)
240         * 
241         * @see java.util.Collection#retainAll(java.util.Collection)
242         */
243        @Override
244        public boolean retainAll(Collection<?> c) {
245                boolean res = false;
246                Iterator<Individual> it = iterator();
247                while (it.hasNext()) {
248                        if (!c.contains(it.next())) {
249                                it.remove();
250                                res = true;
251                        }
252                }
253                return res;
254        }
255
256        /*
257         * (non-Javadoc)
258         * 
259         * @see java.util.Collection#toArray()
260         */
261        @Override
262        public Object[] toArray() {
263                return individuals.toArray();
264        }
265
266        /*
267         * (non-Javadoc)
268         * 
269         * @see java.util.Collection#toArray(T[])
270         */
271        @Override
272        public <T> T[] toArray(T[] a) {
273                return individuals.toArray(a);
274        }
275
276}