152 lines
4.3 KiB
Java
152 lines
4.3 KiB
Java
|
|
/*
|
||
|
|
* 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.
|
||
|
|
* <p><b>WARNING: This class is not thread safe.</b>
|
||
|
|
*/
|
||
|
|
public class CircularQueue implements ICircularQueue {
|
||
|
|
private Object[] data = null;
|
||
|
|
private boolean hasLooped = false;
|
||
|
|
private int nextIndex = 0;
|
||
|
|
|
||
|
|
/**
|
||
|
|
* An iterator over the circular queue.
|
||
|
|
* <p><b>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.</b>
|
||
|
|
*/
|
||
|
|
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//
|