//# 1 errors, 219 messages
//#
/*
    //#RollingList.java:1:1: class: com.dmdirc.util.RollingList
    //#RollingList.java:1:1: method: com.dmdirc.util.RollingList.com.dmdirc.util.RollingList__static_init
 * Copyright (c) 2006-2009 Chris Smith, Shane Mc Cormack, Gregory Holmes
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

package com.dmdirc.util;

import java.util.ArrayList;
import java.util.List;

/**
 * Implements a "rolling list". A rolling list has a maximum capacity, and
 * removes the oldest elements from the list to maintain this capacity.
 * 
 * @param <T> The type if items that this list contains 
 * @author chris
 */
public class RollingList<T> {
   
    /** The items in this rolling list. */
    private final List<T> items = new ArrayList<T>();
    
    /** The maximum capacity of this list. */
    private final int capacity;
    
    /** This list's position pointer. */
    private int position = 0;
    
    /** Whether or not to add a fake empty item to the end of this list. */
    private boolean addEmpty;
    /** The "empty" item to be added. */
    private T empty;
    
    /**
     * Creates a new RollingList of the specified capacity.
     * 
     * @param capacity The capacity of this list.
     */
    public RollingList(final int capacity) {
    //#RollingList.java:56: method: void com.dmdirc.util.RollingList.com.dmdirc.util.RollingList(int)
    //#input(void com.dmdirc.util.RollingList(int)): capacity
    //#input(void com.dmdirc.util.RollingList(int)): this
    //#output(void com.dmdirc.util.RollingList(int)): new ArrayList(RollingList#1) num objects
    //#output(void com.dmdirc.util.RollingList(int)): this.addEmpty
    //#output(void com.dmdirc.util.RollingList(int)): this.capacity
    //#output(void com.dmdirc.util.RollingList(int)): this.items
    //#output(void com.dmdirc.util.RollingList(int)): this.position
    //#new obj(void com.dmdirc.util.RollingList(int)): new ArrayList(RollingList#1)
    //#post(void com.dmdirc.util.RollingList(int)): this.addEmpty == 0
    //#post(void com.dmdirc.util.RollingList(int)): this.position == 0
    //#post(void com.dmdirc.util.RollingList(int)): this.capacity == capacity
    //#post(void com.dmdirc.util.RollingList(int)): init'ed(this.capacity)
    //#post(void com.dmdirc.util.RollingList(int)): this.items == &new ArrayList(RollingList#1)
    //#post(void com.dmdirc.util.RollingList(int)): new ArrayList(RollingList#1) num objects == 1
        this.capacity = capacity;
        this.addEmpty = false;
    }
    //#RollingList.java:59: end of method: void com.dmdirc.util.RollingList.com.dmdirc.util.RollingList(int)

    /**
     * Creates a new RollingList of the specified capacity, with the specified
     * "empty" element appended to the end.
     * 
     * @param capacity The capacity of this list.
     * @param empty The "empty" element to be added
     */    
    public RollingList(final int capacity, final T empty) {
    //#RollingList.java:68: method: void com.dmdirc.util.RollingList.com.dmdirc.util.RollingList(int, Object)
    //#input(void com.dmdirc.util.RollingList(int, Object)): capacity
    //#input(void com.dmdirc.util.RollingList(int, Object)): empty
    //#input(void com.dmdirc.util.RollingList(int, Object)): this
    //#output(void com.dmdirc.util.RollingList(int, Object)): new ArrayList(RollingList#1) num objects
    //#output(void com.dmdirc.util.RollingList(int, Object)): this.addEmpty
    //#output(void com.dmdirc.util.RollingList(int, Object)): this.capacity
    //#output(void com.dmdirc.util.RollingList(int, Object)): this.empty
    //#output(void com.dmdirc.util.RollingList(int, Object)): this.items
    //#output(void com.dmdirc.util.RollingList(int, Object)): this.position
    //#new obj(void com.dmdirc.util.RollingList(int, Object)): new ArrayList(RollingList#1)
    //#post(void com.dmdirc.util.RollingList(int, Object)): this.addEmpty == 1
    //#post(void com.dmdirc.util.RollingList(int, Object)): new ArrayList(RollingList#1) num objects == 1
    //#post(void com.dmdirc.util.RollingList(int, Object)): this.capacity == capacity
    //#post(void com.dmdirc.util.RollingList(int, Object)): init'ed(this.capacity)
    //#post(void com.dmdirc.util.RollingList(int, Object)): this.empty == empty
    //#post(void com.dmdirc.util.RollingList(int, Object)): init'ed(this.empty)
    //#post(void com.dmdirc.util.RollingList(int, Object)): this.items == &new ArrayList(RollingList#1)
    //#post(void com.dmdirc.util.RollingList(int, Object)): this.position == 0
        this.capacity = capacity;
        this.addEmpty = true;
        this.empty = empty;
    }
    //#RollingList.java:72: end of method: void com.dmdirc.util.RollingList.com.dmdirc.util.RollingList(int, Object)

    /**
     * Removes the specified element from this list.
     * 
     * @param o The object to be removed from the list.
     * @return True if the list contained the specified element, false otherwise.
     */
    public boolean remove(final Object o) {
        return items.remove(o);
    //#RollingList.java:81: method: bool com.dmdirc.util.RollingList.remove(Object)
    //#input(bool remove(Object)): o
    //#input(bool remove(Object)): this
    //#input(bool remove(Object)): this.items
    //#output(bool remove(Object)): return_value
    //#pre[3] (bool remove(Object)): this.items != null
    //#post(bool remove(Object)): init'ed(return_value)
    //#RollingList.java:81: end of method: bool com.dmdirc.util.RollingList.remove(Object)
    }

    /**
     * Determines if this list is currently empty.
     * 
     * @return True if the list is empty, false otherwise.
     */
    public boolean isEmpty() {
        return items.isEmpty();
    //#RollingList.java:90: method: bool com.dmdirc.util.RollingList.isEmpty()
    //#input(bool isEmpty()): this
    //#input(bool isEmpty()): this.items
    //#output(bool isEmpty()): return_value
    //#pre[2] (bool isEmpty()): this.items != null
    //#post(bool isEmpty()): init'ed(return_value)
    //#RollingList.java:90: end of method: bool com.dmdirc.util.RollingList.isEmpty()
    }

    /**
     * Retrieves the item at the specified index in this list.
     * 
     * @param index The index to look up
     * @return The item at the specified index
     */
    public T get(final int index) {
        return items.get(index);
    //#RollingList.java:100: method: Object com.dmdirc.util.RollingList.get(int)
    //#input(Object get(int)): index
    //#input(Object get(int)): this
    //#input(Object get(int)): this.items
    //#output(Object get(int)): return_value
    //#pre[3] (Object get(int)): this.items != null
    //#post(Object get(int)): init'ed(return_value)
    //#RollingList.java:100: end of method: Object com.dmdirc.util.RollingList.get(int)
    }

    /**
     * Determines if this list contains the specified object.
     * 
     * @param o The object to be checked
     * @return True if this list contains the item, false otherwise.
     */
    public boolean contains(final Object o) {
        return items.contains(o);
    //#RollingList.java:110: method: bool com.dmdirc.util.RollingList.contains(Object)
    //#input(bool contains(Object)): o
    //#input(bool contains(Object)): this
    //#input(bool contains(Object)): this.items
    //#output(bool contains(Object)): return_value
    //#pre[3] (bool contains(Object)): this.items != null
    //#post(bool contains(Object)): init'ed(return_value)
    //#RollingList.java:110: end of method: bool com.dmdirc.util.RollingList.contains(Object)
    }

    /**
     * Clears all items from this list.
     */
    public void clear() {
        items.clear();
    //#RollingList.java:117: method: void com.dmdirc.util.RollingList.clear()
    //#input(void clear()): this
    //#input(void clear()): this.items
    //#pre[2] (void clear()): this.items != null
    }  
    //#RollingList.java:118: end of method: void com.dmdirc.util.RollingList.clear()
    
    /**
     * Adds the specified item to this list. If the list has reached its
     * maximum capacity, this method will remove elements from the start of the
     * list until there is sufficient room for the new element.
     * 
     * @param e The element to be added to the list.
     * @return True
     */
    public boolean add(T e) {
        while (items.size() > capacity - 1) {
    //#RollingList.java:129: method: bool com.dmdirc.util.RollingList.add(Object)
    //#input(bool add(Object)): e
    //#input(bool add(Object)): this
    //#input(bool add(Object)): this.capacity
    //#input(bool add(Object)): this.items
    //#input(bool add(Object)): this.position
    //#output(bool add(Object)): return_value
    //#output(bool add(Object)): this.position
    //#pre[4] (bool add(Object)): this.capacity >= -2_147_483_647
    //#pre[5] (bool add(Object)): this.items != null
    //#pre[2] (bool add(Object)): (soft) this.position >= -2_147_483_647
    //#post(bool add(Object)): init'ed(return_value)
    //#post(bool add(Object)): init'ed(this.position)
    //#post(bool add(Object)): this.position - old this.position in {-6_442_450_943..0}
            items.remove(0);
            position--;
    //#RollingList.java:131: ?overflow
    //#    this.position in {-2_147_483_647..4_294_967_296}
    //#    severity: LOW
    //#    class: com.dmdirc.util.RollingList
    //#    method: bool add(Object)
    //#    basic block: bb_3
    //#    assertion: this.position in {-2_147_483_647..4_294_967_296}
    //#    VN: this.position - 1
    //#    Expected: {-2_147_483_648..4_294_967_295, Invalid}
    //#    Bad: {-2_147_483_649}
    //#    Attribs:  Int  Bad singleton  Bad < Exp
        }
        
        return items.add(e);
    //#RollingList.java:134: end of method: bool com.dmdirc.util.RollingList.add(Object)
    }
    
    /**
     * Retrieves the current position within the list.
     * 
     * @return This list's positional pointer
     */
    public int getPosition() {
        return position;
    //#RollingList.java:143: method: int com.dmdirc.util.RollingList.getPosition()
    //#input(int getPosition()): this
    //#input(int getPosition()): this.position
    //#output(int getPosition()): return_value
    //#pre[2] (int getPosition()): init'ed(this.position)
    //#post(int getPosition()): return_value == this.position
    //#post(int getPosition()): init'ed(return_value)
    //#RollingList.java:143: end of method: int com.dmdirc.util.RollingList.getPosition()
    }

    /**
     * Sets the positional pointer of this list.
     * 
     * @param position The new position
     */
    public void setPosition(int position) {
        this.position = position;
    //#RollingList.java:152: method: void com.dmdirc.util.RollingList.setPosition(int)
    //#input(void setPosition(int)): position
    //#input(void setPosition(int)): this
    //#output(void setPosition(int)): this.position
    //#post(void setPosition(int)): this.position == position
    //#post(void setPosition(int)): init'ed(this.position)
    }    
    //#RollingList.java:153: end of method: void com.dmdirc.util.RollingList.setPosition(int)
    
    /**
     * Determines if there is an element after the positional pointer of the list.
     * 
     * @return True if there is an element, false otherwise.
     */
    public boolean hasNext() {
        return (items.size() > position + 1) || ((items.size() > position) && addEmpty);
    //#RollingList.java:161: method: bool com.dmdirc.util.RollingList.hasNext()
    //#input(bool hasNext()): this
    //#input(bool hasNext()): this.addEmpty
    //#input(bool hasNext()): this.items
    //#input(bool hasNext()): this.position
    //#output(bool hasNext()): return_value
    //#pre[3] (bool hasNext()): this.items != null
    //#pre[4] (bool hasNext()): init'ed(this.position)
    //#pre[2] (bool hasNext()): (soft) init'ed(this.addEmpty)
    //#post(bool hasNext()): init'ed(return_value)
    //#RollingList.java:161: end of method: bool com.dmdirc.util.RollingList.hasNext()
    }
    
    /**
     * Retrieves the element after the positional pointer of the list.
     * 
     * @return The next element in the list
     */
    public T getNext() {
        if (items.size() > position + 1 || !addEmpty) {
    //#RollingList.java:170: method: Object com.dmdirc.util.RollingList.getNext()
    //#input(Object getNext()): __Descendant_Table[com/dmdirc/util/RollingList]
    //#input(Object getNext()): __Descendant_Table[others]
    //#input(Object getNext()): __Dispatch_Table.get(I)Ljava/lang/Object;
    //#input(Object getNext()): this
    //#input(Object getNext()): this.__Tag
    //#input(Object getNext()): this.addEmpty
    //#input(Object getNext()): this.empty
    //#input(Object getNext()): this.items
    //#input(Object getNext()): this.position
    //#output(Object getNext()): return_value
    //#output(Object getNext()): this.position
    //#pre[1] (Object getNext()): this.position <= 4_294_967_294
    //#pre[6] (Object getNext()): this.items != null
    //#pre[3] (Object getNext()): (soft) this.__Tag == com/dmdirc/util/RollingList
    //#pre[4] (Object getNext()): (soft) init'ed(this.addEmpty)
    //#pre[5] (Object getNext()): (soft) init'ed(this.empty)
    //#post(Object getNext()): init'ed(return_value)
    //#post(Object getNext()): this.position == old this.position + 1
    //#post(Object getNext()): this.position >= -2_147_483_647
    //#unanalyzed(Object getNext()): Effects-of-calling:java.util.List:get
    //#test_vector(Object getNext()): this.addEmpty: {1}, {0}
            return get(++position);
        } else {
            position++;
            return empty;
    //#RollingList.java:174: end of method: Object com.dmdirc.util.RollingList.getNext()
        }
    }
    
    /**
     * Determines if there is an element befpre the positional pointer of the list.
     * 
     * @return True if there is an element, false otherwise.
     */    
    public boolean hasPrevious() {
        return 0 < position;
    //#RollingList.java:184: method: bool com.dmdirc.util.RollingList.hasPrevious()
    //#input(bool hasPrevious()): this
    //#input(bool hasPrevious()): this.position
    //#output(bool hasPrevious()): return_value
    //#pre[2] (bool hasPrevious()): init'ed(this.position)
    //#post(bool hasPrevious()): init'ed(return_value)
    //#RollingList.java:184: end of method: bool com.dmdirc.util.RollingList.hasPrevious()
    }
    
    /**
     * Retrieves the element before the positional pointer of the list.
     * 
     * @return The previous element in the list
     */    
    public T getPrevious() {
        return get(--position);
    //#RollingList.java:193: method: Object com.dmdirc.util.RollingList.getPrevious()
    //#input(Object getPrevious()): __Descendant_Table[com/dmdirc/util/RollingList]
    //#input(Object getPrevious()): __Descendant_Table[others]
    //#input(Object getPrevious()): __Dispatch_Table.get(I)Ljava/lang/Object;
    //#input(Object getPrevious()): this
    //#input(Object getPrevious()): this.__Tag
    //#input(Object getPrevious()): this.items
    //#input(Object getPrevious()): this.position
    //#output(Object getPrevious()): return_value
    //#output(Object getPrevious()): this.position
    //#pre[1] (Object getPrevious()): this.position >= -2_147_483_647
    //#pre[3] (Object getPrevious()): this.__Tag == com/dmdirc/util/RollingList
    //#pre[4] (Object getPrevious()): this.items != null
    //#post(Object getPrevious()): init'ed(return_value)
    //#post(Object getPrevious()): this.position == old this.position - 1
    //#post(Object getPrevious()): this.position <= 4_294_967_294
    //#unanalyzed(Object getPrevious()): Effects-of-calling:java.util.List:get
    //#RollingList.java:193: end of method: Object com.dmdirc.util.RollingList.getPrevious()
    }    
    
    /**
     * Sets the positional pointer of this list to the end.
     */
    public void seekToEnd() {
        position = items.size();
    //#RollingList.java:200: method: void com.dmdirc.util.RollingList.seekToEnd()
    //#input(void seekToEnd()): this
    //#input(void seekToEnd()): this.items
    //#output(void seekToEnd()): this.position
    //#pre[2] (void seekToEnd()): this.items != null
    //#post(void seekToEnd()): init'ed(this.position)
    }
    //#RollingList.java:201: end of method: void com.dmdirc.util.RollingList.seekToEnd()
    
    /**
     * Sets the positional pointer of this list to the start.
     */
    public void seekToStart() {
        position = 0;
    //#RollingList.java:207: method: void com.dmdirc.util.RollingList.seekToStart()
    //#input(void seekToStart()): this
    //#output(void seekToStart()): this.position
    //#post(void seekToStart()): this.position == 0
    }
    //#RollingList.java:208: end of method: void com.dmdirc.util.RollingList.seekToStart()
    
    /**
     * Retrieves a list of items that this rolling list contains.
     * 
     * @return A list of items in this rolling list.
     */
    public List<T> getList() {
        return new ArrayList<T>(items);
    //#RollingList.java:216: method: List com.dmdirc.util.RollingList.getList()
    //#input(List getList()): this
    //#input(List getList()): this.items
    //#output(List getList()): new ArrayList(getList#1) num objects
    //#output(List getList()): return_value
    //#new obj(List getList()): new ArrayList(getList#1)
    //#post(List getList()): return_value == &new ArrayList(getList#1)
    //#post(List getList()): new ArrayList(getList#1) num objects == 1
    //#RollingList.java:216: end of method: List com.dmdirc.util.RollingList.getList()
    }

}
    //#output(com.dmdirc.util.RollingList__static_init): __Descendant_Table[com/dmdirc/util/RollingList]
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.add(Ljava/lang/Object;)Z
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.clear()V
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.contains(Ljava/lang/Object;)Z
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.get(I)Ljava/lang/Object;
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.getList()Ljava/util/List;
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.getNext()Ljava/lang/Object;
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.getPosition()I
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.getPrevious()Ljava/lang/Object;
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.hasNext()Z
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.hasPrevious()Z
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.isEmpty()Z
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.remove(Ljava/lang/Object;)Z
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.seekToEnd()V
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.seekToStart()V
    //#output(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.setPosition(I)V
    //#post(com.dmdirc.util.RollingList__static_init): __Descendant_Table[com/dmdirc/util/RollingList] == &__Dispatch_Table
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.add(Ljava/lang/Object;)Z == &add
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.clear()V == &clear
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.contains(Ljava/lang/Object;)Z == &contains
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.get(I)Ljava/lang/Object; == &get
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.getList()Ljava/util/List; == &getList
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.getNext()Ljava/lang/Object; == &getNext
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.getPosition()I == &getPosition
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.getPrevious()Ljava/lang/Object; == &getPrevious
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.hasNext()Z == &hasNext
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.hasPrevious()Z == &hasPrevious
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.isEmpty()Z == &isEmpty
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.remove(Ljava/lang/Object;)Z == &remove
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.seekToEnd()V == &seekToEnd
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.seekToStart()V == &seekToStart
    //#post(com.dmdirc.util.RollingList__static_init): __Dispatch_Table.setPosition(I)V == &setPosition
    //#RollingList.java:: end of method: com.dmdirc.util.RollingList.com.dmdirc.util.RollingList__static_init
    //#RollingList.java:: end of class: com.dmdirc.util.RollingList
