package de.geolykt.starloader.deobf;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Queue;
import java.util.Spliterator;
import java.util.Stack;
/**
* A Last-in-first-out (LIFO) queue that uses a Deque as a delegate. Technically
* the {@link Deque} can be used directly, however the issue is that there is a
* rather high chance of logical programmer errors as {@link Queue#add(Object)}
* does not specify the insertion order and {@link ArrayDeque#add(Object)} adds
* the element to the tail of the queue and not to the head as it might be
* expected. This class resolves that issue.
*
*
* Alternatively the {@link Stack} class could be used as a LIFO queue, however
* it has the drawbacks of almost every method being synchronised and thus not
* being very good in concurrent environments as well of implementing
* {@link Deque} and thus also inheriting the above stated issue.
*
* @author Geolykt
*
* @param The type of elements that should be stored in the queue.
*/
public class LIFOQueue implements Iterable {
private final LinkedList delegate;
public LIFOQueue(LinkedList delegate) {
this.delegate = delegate;
}
/**
* Calls {@link Deque#addFirst(Object)}, which adds an element to the head of
* the queue. If the underlying Dequeue has capacity restrictions, it throws an
* {@link IllegalStateException}. Some Dequeues (such as {@link ArrayDeque}) may
* not accept null elements and will throw a {@link NullPointerException}, which
* would be propagated by this method.
*
* @param element The element to add
*/
public void add(E element) {
delegate.addFirst(element);
}
/**
* Clears all elements from the queue.
*/
public void clear() {
delegate.clear();
}
@Override
public boolean equals(Object obj) {
if (obj instanceof LIFOQueue) {
return delegate.equals(((LIFOQueue>) obj).delegate);
}
return delegate.equals(obj);
}
/**
* Obtains the dequeue delegate for more advanced operations.
*
* @return The delegate Deque
*/
public Deque getDelegate() {
return delegate;
}
/**
* Obtains the {@link LinkedList} delegate for more advanced operations.
*
* @return The delegate {@link LinkedList}.
*/
public LinkedList getDelegateList() {
return delegate;
}
/**
* Obtains the element at the head of the queue, if there is no such element
* then a {@link NoSuchElementException} will be thrown. This method calls
* {@link Deque#getFirst()}.
*
* @return The element at the head of the queue.
* @throws NoSuchElementException If there are no elements in the queue.
*/
public E getHead() {
return delegate.getFirst();
}
/**
* Obtains the amount of elements left in the queue.
*
* @return The amount of elements in the queue
* @see Deque#size()
*/
public int getSize() {
return delegate.size();
}
@Override
public int hashCode() {
return delegate.hashCode();
}
/**
* Checks whether the queue is empty. This method corresponds to
* {@link Deque#isEmpty()}. This method should generally only return true is
* {@link #getSize()} is equal to 0.
*
* @return False if there is at least one element left in the queue, otherwise
* true.
*/
public boolean isEmpty() {
return delegate.isEmpty();
}
@Override
public Iterator iterator() {
return delegate.iterator();
}
/**
* Calls {@link Deque#remove()} and thus throws an exception if there is no
* element left in the queue. If there is an element left in the queue, the
* element at the head of the queue is removed from the queue and returned.
*
* @return The removed element.
* @throws NoSuchElementException If there are no elements left in the queue.
*/
public E remove() {
return delegate.remove();
}
@Override
public Spliterator spliterator() {
return delegate.spliterator();
}
@Override
public String toString() {
return delegate.toString();
}
}