/* * Copyright (c) 2002,2009 Declarative Engineering LLC. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Declarative Engineering LLC * verson 1 which accompanies this distribution, and is available at * http://declarativeengineering.com/legal/DE_Developer_License_v1.txt */ package com.common.util; import com.common.debug.Debug; import com.common.debug.QueuedLog; /** * Implements a circular queue - FIFO (first in first out) collection where the size is fixed and new entries will overwrite the oldest entries and entries cannot be removed. *
WARNING: This class is not thread safe. */ public class CircularQueue implements ICircularQueue { private Object[] data = null; private boolean hasLooped = false; private int nextIndex = 0; /** * An iterator over the circular queue. *
WARNING: This class is not thread safe. The iterator is designed to only be used either as a forward or reverse iterator, but not necessarily both at the same time. */ private class Iterator implements IReversableIterator { private int startIndex = -1; private int index = -1; private Iterator() { }//Iterator()// public boolean remove() { //Values cannot be removed from a circular queue.// throw new com.common.exception.MethodNotSupportedException(); }//remove()// public boolean hasNext() { return getSize() > 0 && (index == -1 || index != startIndex); }//hasNext()// public boolean hasPrevious() { return getSize() > 0 && (index == -1 || index != startIndex); }//hasPrevious()// public Object next() { Object result; if(!hasNext()) { throw new IndexOutOfBoundsException("Call iterator.hasNext() before calling iterator.next()"); }//if// if(index == -1) { if(CircularQueue.this.hasLooped) { startIndex = index = CircularQueue.this.nextIndex == 0 ? CircularQueue.this.data.length - 1 : CircularQueue.this.nextIndex - 1; }//if// else { index = 0; startIndex = CircularQueue.this.nextIndex; }//else// }//if// //Increment & wrap the index.// if(++index == CircularQueue.this.data.length && CircularQueue.this.hasLooped) { index = 0; }//if// result = data[index]; return result; }//next()// public Object previous() { Object result; if(!hasPrevious()) { throw new IndexOutOfBoundsException("Call iterator.hasPrevious() before calling iterator.previous()"); }//if// if(index == -1) { if(CircularQueue.this.hasLooped) { startIndex = index = CircularQueue.this.nextIndex == 0 ? CircularQueue.this.data.length : CircularQueue.this.nextIndex; }//if// else { index = CircularQueue.this.nextIndex; startIndex = 0; }//else// }//if// if(--index == -1 && CircularQueue.this.hasLooped) { index = CircularQueue.this.data.length - 1; }//if// result = data[index]; return result; }//previous()// public void resetToFront() { startIndex = index = -1; }//resetToFront()// public void resetToBack() { startIndex = index = -1; }//resetToBack()// }//Iterator// /** * CircularQueue constructor. */ public CircularQueue(int size) { super(); data = new Object[size]; }//CircularQueue()// /** * ICircularQueue#enqueue(Object) */ public boolean enqueue(Object value) { data[nextIndex++] = value; if(nextIndex == data.length) { nextIndex = 0; hasLooped = true; }//if// return true; }//enqueue()// /** * ICircularQueue#getSize() */ public int getSize() { return hasLooped ? data.length : nextIndex; }//getSize()// /** * ICircularQueue#iterator() */ public IReversableIterator iterator() { return new Iterator(); }//iterator()// /** * Reads the collection from the stream. * @param in java.io.ObjectInput The stream that the object data can be read from. */ public void readExternal(java.io.ObjectInput in) throws java.io.IOException, ClassNotFoundException { data = (Object[]) in.readObject(); hasLooped = in.readBoolean(); nextIndex = in.readInt(); }//readExternal()// /** * Writes the collection to the stream. * @param out java.io.ObjectOutput The stream that the object data can be written to. */ public void writeExternal(java.io.ObjectOutput out) throws java.io.IOException { out.writeObject(data); out.writeBoolean(hasLooped); out.writeInt(nextIndex); }//writeExternal()// }//CircularQueue//