001/**
002 *   GRANITE DATA SERVICES
003 *   Copyright (C) 2006-2013 GRANITE DATA SERVICES S.A.S.
004 *
005 *   This file is part of the Granite Data Services Platform.
006 *
007 *                               ***
008 *
009 *   Community License: GPL 3.0
010 *
011 *   This file is free software: you can redistribute it and/or modify
012 *   it under the terms of the GNU General Public License as published
013 *   by the Free Software Foundation, either version 3 of the License,
014 *   or (at your option) any later version.
015 *
016 *   This file is distributed in the hope that it will be useful, but
017 *   WITHOUT ANY WARRANTY; without even the implied warranty of
018 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
019 *   GNU General Public License for more details.
020 *
021 *   You should have received a copy of the GNU General Public License
022 *   along with this program. If not, see <http://www.gnu.org/licenses/>.
023 *
024 *                               ***
025 *
026 *   Available Commercial License: GraniteDS SLA 1.0
027 *
028 *   This is the appropriate option if you are creating proprietary
029 *   applications and you are not prepared to distribute and share the
030 *   source code of your application under the GPL v3 license.
031 *
032 *   Please visit http://www.granitedataservices.com/license for more
033 *   details.
034 */
035package org.granite.client.collection;
036
037import java.util.Collection;
038import java.util.Iterator;
039import java.util.Set;
040
041import org.granite.client.collection.CollectionChangeListener;
042import org.granite.client.collection.CollectionChangeSupport;
043import org.granite.client.collection.CollectionChangeEvent.Kind;
044
045/**
046 * @author William DRAI
047 */
048public class ObservableSet<E> implements Set<E> {
049        
050        protected CollectionChangeSupport ccs = new CollectionChangeSupport(this);
051        private final Set<E> wrappedSet;
052        
053        public ObservableSet(Set<E> set) {
054                this.wrappedSet = set;
055        }
056        
057        protected Set<E> getWrappedList() {
058                return wrappedSet;
059        }
060        
061        public void addCollectionChangeListener(CollectionChangeListener listener) {
062                ccs.addCollectionChangeListener(listener);
063        }
064        
065        public void removeCollectionChangeListener(CollectionChangeListener listener) {
066                ccs.removeCollectionChangeListener(listener);
067        }
068
069        @Override
070        public boolean add(E element) {
071                boolean added = wrappedSet.add(element);
072                if (added)
073                        ccs.fireCollectionChangeEvent(Kind.ADD, null, new Object[] { element });
074                return added;
075        }
076
077        @Override
078        public boolean addAll(Collection<? extends E> elements) {
079                boolean added = wrappedSet.addAll(elements);
080                if (added)
081                        ccs.fireCollectionChangeEvent(Kind.ADD, null, elements.toArray());
082                return added;
083        }
084
085        @Override
086        public boolean remove(Object element) {
087                boolean removed = wrappedSet.remove(element);
088                if (removed)
089                        ccs.fireCollectionChangeEvent(Kind.REMOVE, null, new Object[] { removed });
090                return removed;
091        }
092
093        @Override
094        public boolean removeAll(Collection<?> collection) {
095                boolean removed = false;
096                for (Object element : collection) {
097                        if (remove(element))
098                                removed = true;
099                }
100                return removed;
101        }
102
103        @Override
104        public boolean retainAll(Collection<?> collection) {
105                boolean changed = false;
106                for (Object element : collection) {
107                        if (!wrappedSet.contains(element) && remove(element))
108                                changed = true;
109                }
110                return changed;
111        }
112
113        @Override
114        public void clear() {
115                if (wrappedSet.size() == 0)
116                        return;
117                Object[] elements = wrappedSet.toArray();
118                wrappedSet.clear();
119                ccs.fireCollectionChangeEvent(Kind.CLEAR, null, elements);              
120        }
121
122        @Override
123        public boolean contains(Object element) {
124                return wrappedSet.contains(element);
125        }
126
127        @Override
128        public boolean containsAll(Collection<?> collection) {
129                return wrappedSet.containsAll(collection);
130        }
131
132        @Override
133        public boolean isEmpty() {
134                return wrappedSet.isEmpty();
135        }
136
137        @Override
138        public int size() {
139                return wrappedSet.size();
140        }
141
142        @Override
143        public Object[] toArray() {
144                return wrappedSet.toArray();
145        }
146
147        @Override
148        public <T> T[] toArray(T[] array) {
149                return wrappedSet.toArray(array);
150        }
151        
152        @Override
153        public Iterator<E> iterator() {
154                return new IteratorWrapper(wrappedSet.iterator());
155        }
156        
157        
158        private class IteratorWrapper implements Iterator<E> {
159                
160                private final Iterator<E> wrappedIterator;
161                private E element;
162                
163                public IteratorWrapper(Iterator<E> iterator) {
164                        this.wrappedIterator = iterator;
165                }
166
167                public boolean hasNext() {
168                        return wrappedIterator.hasNext();
169                }
170
171                public E next() {
172                        element = wrappedIterator.next();
173                        return element;
174                }
175
176                public void remove() {
177                        wrappedIterator.remove();
178                        ccs.fireCollectionChangeEvent(Kind.REMOVE, null, new Object[] { element });
179                }
180        }
181}