001package components.sortingmachine;
002
003import java.util.Collections;
004import java.util.Comparator;
005import java.util.Iterator;
006import java.util.LinkedList;
007import java.util.List;
008import java.util.NoSuchElementException;
009
010/**
011 * {@code SortingMachine} represented as {@link java.util.List java.util.List}
012 * (using an embedding of {@link java.util.Collections#sort(List, Comparator)
013 * java.util.Collections.sort}), with implementations of primary methods.
014 *
015 * @param <T>
016 *            type of {@code SortingMachine} entries
017 * @mathdefinitions {@code
018 * IS_TOTAL_PREORDER (
019 *   r: binary relation on T
020 *  ) : boolean is
021 *  for all x, y, z: T
022 *   ((r(x, y) or r(y, x))  and
023 *    (if (r(x, y) and r(y, z)) then r(x, z)))
024 *
025 * IS_SORTED (
026 *   s: string of T,
027 *   r: binary relation on T
028 *  ) : boolean is
029 *  for all x, y: T where (<x, y> is substring of s) (r(x, y))
030 * }
031 * @convention <pre>
032 * IS_TOTAL_PREORDER([relation computed by $this.machineOrder.compare method])  and
033 * if not $this.insertionMode then
034 *  IS_SORTED($this.entries, [relation computed by $this.machineOrder.compare method])
035 * </pre>
036 * @correspondence <pre>
037 * this = ($this.insertionMode, $this.machineOrder, [value of $this.entries])
038 * </pre>
039 */
040public class SortingMachine1L<T> extends SortingMachineSecondary<T> {
041
042    /*
043     * Private members --------------------------------------------------------
044     */
045
046    /**
047     * Insertion mode.
048     */
049    private boolean insertionMode;
050
051    /**
052     * Order.
053     */
054    private Comparator<T> machineOrder;
055
056    /**
057     * Entries.
058     */
059    private List<T> entries;
060
061    /**
062     * Creator of initial representation.
063     *
064     * @param order
065     *            total preorder for sorting
066     */
067    private void createNewRep(Comparator<T> order) {
068        this.insertionMode = true;
069        this.machineOrder = order;
070        this.entries = new LinkedList<T>();
071    }
072
073    /*
074     * Constructors -----------------------------------------------------------
075     */
076
077    /**
078     * Constructor from order.
079     *
080     * @param order
081     *            total preorder for sorting
082     */
083    public SortingMachine1L(Comparator<T> order) {
084        this.createNewRep(order);
085    }
086
087    /*
088     * Standard methods -------------------------------------------------------
089     */
090
091    @SuppressWarnings("unchecked")
092    @Override
093    public final SortingMachine<T> newInstance() {
094        try {
095            return this.getClass().getConstructor(Comparator.class)
096                    .newInstance(this.machineOrder);
097        } catch (ReflectiveOperationException e) {
098            throw new AssertionError(
099                    "Cannot construct object of type " + this.getClass());
100        }
101    }
102
103    @Override
104    public final void clear() {
105        this.createNewRep(this.machineOrder);
106    }
107
108    @Override
109    public final void transferFrom(SortingMachine<T> source) {
110        assert source != null : "Violation of: source is not null";
111        assert source != this : "Violation of: source is not this";
112        assert source instanceof SortingMachine1L<?>
113                : "Violation of: source is of dynamic type SortingMachine1L<?>";
114        /*
115         * This cast cannot fail since the assert above would have stopped
116         * execution in that case: source must be of dynamic type
117         * SortingMachine1L<?>, and the ? must be T or the call would not have
118         * compiled.
119         */
120        SortingMachine1L<T> localSource = (SortingMachine1L<T>) source;
121        this.insertionMode = localSource.insertionMode;
122        this.machineOrder = localSource.machineOrder;
123        this.entries = localSource.entries;
124        localSource.createNewRep(localSource.machineOrder);
125    }
126
127    /*
128     * Kernel methods ---------------------------------------------------------
129     */
130
131    @Override
132    public final void add(T x) {
133        assert x != null : "Violation of: x is not null";
134        assert this.isInInsertionMode() : "Violation of: this.insertion_mode";
135        this.entries.add(x);
136    }
137
138    @Override
139    public final void changeToExtractionMode() {
140        assert this.isInInsertionMode() : "Violation of: this.insertion_mode";
141        Collections.sort(this.entries, this.machineOrder);
142        this.insertionMode = false;
143    }
144
145    @Override
146    public final T removeFirst() {
147        assert !this.isInInsertionMode() : "Violation of: not this.insertion_mode";
148        assert this.size() > 0 : "Violation of: this.contents /= {}";
149        return this.entries.remove(0);
150    }
151
152    @Override
153    public final boolean isInInsertionMode() {
154        return this.insertionMode;
155    }
156
157    @Override
158    public final Comparator<T> order() {
159        return this.machineOrder;
160    }
161
162    @Override
163    public final int size() {
164        return this.entries.size();
165    }
166
167    @Override
168    public final Iterator<T> iterator() {
169        return new SortingMachine1LIterator();
170    }
171
172    /**
173     * Implementation of {@code Iterator} interface for {@code SortingMachine1L}
174     * .
175     */
176    private final class SortingMachine1LIterator implements Iterator<T> {
177
178        /**
179         * Representation iterator.
180         */
181        private final Iterator<T> iterator;
182
183        /**
184         * No-argument constructor.
185         */
186        private SortingMachine1LIterator() {
187            this.iterator = SortingMachine1L.this.entries.iterator();
188        }
189
190        @Override
191        public boolean hasNext() {
192            return this.iterator.hasNext();
193        }
194
195        @Override
196        public T next() {
197            assert this.hasNext() : "Violation of: ~this.unseen /= <>";
198            if (!this.hasNext()) {
199                /*
200                 * Exception is supposed to be thrown in this case, but with
201                 * assertion-checking enabled it cannot happen because of assert
202                 * above.
203                 */
204                throw new NoSuchElementException();
205            }
206            return this.iterator.next();
207        }
208
209        @Override
210        public void remove() {
211            throw new UnsupportedOperationException("remove operation not supported");
212        }
213
214    }
215
216}