001package components.set;
002
003import java.util.HashSet;
004import java.util.Iterator;
005import java.util.NoSuchElementException;
006
007/**
008 * {@code Set} represented as a {@link java.util.Set java.util.Set} with
009 * implementations of primary methods.
010 *
011 * @param <T>
012 *            type of {@code Set} elements
013 * @correspondence this = [value of $this]
014 */
015public class Set1L<T> extends SetSecondary<T> {
016
017    /*
018     * Private members --------------------------------------------------------
019     */
020
021    /**
022     * Representation of {@code this}.
023     */
024    private java.util.Set<T> rep;
025
026    /**
027     * Creator of initial representation.
028     */
029    private void createNewRep() {
030        this.rep = new HashSet<T>();
031    }
032
033    /*
034     * Constructors -----------------------------------------------------------
035     */
036
037    /**
038     * No-argument constructor.
039     */
040    public Set1L() {
041        this.createNewRep();
042    }
043
044    /*
045     * Standard methods -------------------------------------------------------
046     */
047
048    @SuppressWarnings("unchecked")
049    @Override
050    public final Set<T> newInstance() {
051        try {
052            return this.getClass().getConstructor().newInstance();
053        } catch (ReflectiveOperationException e) {
054            throw new AssertionError(
055                    "Cannot construct object of type " + this.getClass());
056        }
057    }
058
059    @Override
060    public final void clear() {
061        this.createNewRep();
062    }
063
064    @Override
065    public final void transferFrom(Set<T> source) {
066        assert source != null : "Violation of: source is not null";
067        assert source != this : "Violation of: source is not this";
068        assert source instanceof Set1L<?>
069                : "Violation of: source is of dynamic type Set1L<?>";
070        /*
071         * This cast cannot fail since the assert above would have stopped
072         * execution in that case: source must be of dynamic type Set1L<?>, and
073         * the ? must be T or the call would not have compiled.
074         */
075        Set1L<T> localSource = (Set1L<T>) source;
076        this.rep = localSource.rep;
077        localSource.createNewRep();
078    }
079
080    /*
081     * Kernel methods ---------------------------------------------------------
082     */
083
084    @Override
085    public final void add(T x) {
086        assert x != null : "Violation of: x is not null";
087        assert !this.contains(x) : "Violation of: x is not in this";
088        this.rep.add(x);
089    }
090
091    @Override
092    public final T remove(T x) {
093        assert x != null : "Violation of: x is not null";
094        assert this.contains(x) : "Violation of: x is in this";
095        /*
096         * The following "obvious" code is incorrect because it creates an alias
097         * where one is not specified in the contract (because no alias is
098         * needed). This is a design flaw in java.util.Set that means Set1L is
099         * not a competitive implementation of SetKernel when assertion-checking
100         * is disabled.
101         */
102        // this.rep.remove(x);
103        // return x;
104        /*
105         * Note: null will never be returned, but we still need to initialize.
106         */
107        T itemRemoved = null;
108        Iterator<T> it = this.rep.iterator();
109        while (it.hasNext()) {
110            itemRemoved = it.next();
111            if (itemRemoved.equals(x)) {
112                it.remove();
113                break;
114            }
115        }
116        return itemRemoved;
117    }
118
119    @Override
120    public final T removeAny() {
121        assert this.size() > 0 : "Violation of: |this| > 0";
122        Iterator<T> it = this.rep.iterator();
123        T x = it.next();
124        it.remove();
125        return x;
126    }
127
128    @Override
129    public final boolean contains(T x) {
130        assert x != null : "Violation of: x is not null";
131        return this.rep.contains(x);
132    }
133
134    @Override
135    public final int size() {
136        return this.rep.size();
137    }
138
139    /*
140     * This implementation is simple, but technically permits a client to call
141     * the optional remove method of the iterator; the more complex code that
142     * follows prevents this.
143     */
144    // @Override
145    // public final Iterator<T> iterator() {
146    //     return this.rep.iterator();
147    // }
148
149    @Override
150    public final Iterator<T> iterator() {
151        return new Set1LIterator();
152    }
153
154    /**
155     * Implementation of {@code Iterator} interface for {@code Set1L}.
156     */
157    private final class Set1LIterator implements Iterator<T> {
158
159        /**
160         * Representation iterator.
161         */
162        private final Iterator<T> iterator;
163
164        /**
165         * No-argument constructor.
166         */
167        private Set1LIterator() {
168            this.iterator = Set1L.this.rep.iterator();
169        }
170
171        @Override
172        public boolean hasNext() {
173            return this.iterator.hasNext();
174        }
175
176        @Override
177        public T next() {
178            assert this.hasNext() : "Violation of: ~this.unseen /= <>";
179            if (!this.hasNext()) {
180                /*
181                 * Exception is supposed to be thrown in this case, but with
182                 * assertion-checking enabled it cannot happen because of assert
183                 * above.
184                 */
185                throw new NoSuchElementException();
186            }
187            return this.iterator.next();
188        }
189
190        @Override
191        public void remove() {
192            throw new UnsupportedOperationException("remove operation not supported");
193        }
194
195    }
196
197}