001/* Copyright (C) 2013 TU Dortmund
002 * This file is part of AutomataLib, http://www.automatalib.net/.
003 * 
004 * AutomataLib is free software; you can redistribute it and/or
005 * modify it under the terms of the GNU Lesser General Public
006 * License version 3.0 as published by the Free Software Foundation.
007 * 
008 * AutomataLib is distributed in the hope that it will be useful,
009 * but WITHOUT ANY WARRANTY; without even the implied warranty of
010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
011 * Lesser General Public License for more details.
012 * 
013 * You should have received a copy of the GNU Lesser General Public
014 * License along with AutomataLib; if not, see
015 * http://www.gnu.de/documents/lgpl.en.html.
016 */
017package net.automatalib.commons.smartcollections;
018
019import java.util.AbstractCollection;
020import java.util.Collection;
021import java.util.Iterator;
022import java.util.Objects;
023
024
025/**
026 * This class eases the implementation of the {@link SmartCollection}
027 * interface. It is comparable to {@link AbstractCollection} from the
028 * Java Collections Framework.
029 * 
030 * A class extending this abstract class has to implement the following
031 * methods:
032 * - {@link Collection#size()}
033 * - {@link SmartCollection#get(ElementReference)}
034 * - {@link SmartCollection#referenceIterator()}
035 * - {@link SmartCollection#referencedAdd(Object)}
036 * - {@link SmartCollection#remove(ElementReference)}
037 * - {@link SmartCollection#replace(ElementReference, Object)}
038 * 
039 * @author Malte Isberner <malte.isberner@gmail.com>
040 *
041 * @param <E> element class.
042 */
043public abstract class AbstractSmartCollection<E> extends AbstractCollection<E> implements SmartCollection<E> {
044        
045        /*
046         * An iterator for iterating over the concrete elements, based on the
047         * iteration over the element references.
048         */
049        private class DeRefIterator implements Iterator<E> {
050                // the reference iterator
051                private Iterator<ElementReference> refIterator;
052                
053                /**
054                 * Constructor.
055                 * @param refIterator the reference iterator.
056                 */
057                public DeRefIterator(Iterator<ElementReference> refIterator) {
058                        this.refIterator = refIterator;
059                }
060                
061                /*
062                 * (non-Javadoc)
063                 * @see java.util.Iterator#hasNext()
064                 */
065                @Override
066                public boolean hasNext() {
067                        return refIterator.hasNext();
068                }
069                
070                /*
071                 * (non-Javadoc)
072                 * @see java.util.Iterator#next()
073                 */
074                @Override
075                public E next() {
076                        return get(refIterator.next());
077                }
078                
079                /*
080                 * (non-Javadoc)
081                 * @see java.util.Iterator#remove()
082                 */
083                @Override
084                public void remove() {
085                        refIterator.remove();
086                }
087        }
088
089        /*
090         * (non-Javadoc)
091         * @see de.ls5.collections.SmartCollection#addAll(java.lang.Iterable)
092         */
093        @Override
094        public void addAll(Iterable<? extends E> iterable) {
095                for(E e : iterable)
096                        add(e);
097        }
098        
099        /*
100         * (non-Javadoc)
101         * @see de.ls5.collections.SmartCollection#addAll(T[])
102         */
103        @Override
104        public <T extends E> void addAll(T[] array) {
105                for(T t : array)
106                        add(t);
107        }
108
109        /*
110         * (non-Javadoc)
111         * @see de.ls5.collections.SmartCollection#choose()
112         */
113        @Override
114        public E choose() {
115                return iterator().next();
116        }
117
118        /*
119         * (non-Javadoc)
120         * @see de.ls5.collections.SmartCollection#chooseRef()
121         */
122        @Override
123        public ElementReference chooseRef() {
124                return referenceIterator().next();
125        }
126
127
128        /*
129         * (non-Javadoc)
130         * @see java.util.AbstractCollection#add(java.lang.Object)
131         */
132        @Override
133        public boolean add(E e) {
134                referencedAdd(e);
135                return true;
136        }
137
138        
139        /*
140         * (non-Javadoc)
141         * @see de.ls5.collections.SmartCollection#references()
142         */
143        @Override
144        public Iterable<ElementReference> references() {
145                return new Iterable<ElementReference>() {
146                        @Override
147                        public Iterator<ElementReference> iterator() {
148                                return referenceIterator();
149                        }
150                };
151        }
152
153        /*
154         * (non-Javadoc)
155         * @see java.util.AbstractCollection#iterator()
156         */
157        @Override
158        public Iterator<E> iterator() {
159                return new DeRefIterator(referenceIterator());
160        }
161
162        /*
163         * (non-Javadoc)
164         * @see de.ls5.collections.SmartCollection#find(java.lang.Object)
165         */
166        @Override
167        public ElementReference find(Object element) {
168                for(ElementReference ref : references()) {
169                        E current = get(ref);
170                        if(Objects.equals(current, element))
171                                return ref;
172                }
173                
174                return null;
175        }
176        
177        
178        /*
179         * (non-Javadoc)
180         * @see java.util.AbstractCollection#remove(java.lang.Object)
181         */
182        @Override
183        public boolean remove(Object element) {
184                ElementReference ref = find(element);
185                if(ref == null)
186                        return false;
187                remove(ref);
188                return true;
189        }
190
191        /*
192         * (non-Javadoc)
193         * @see de.ls5.smartcollections.SmartCollection#deepClear()
194         */
195        @Override
196        public void deepClear() {
197                clear();
198        }
199
200        /*
201         * (non-Javadoc)
202         * @see de.ls5.smartcollections.SmartCollection#quickClear()
203         */
204        @Override
205        public void quickClear() {
206                clear();
207        }
208        
209        
210}