1
0
Fork 0
mirror of https://github.com/correl/mage.git synced 2025-04-11 09:11:12 -09:00
mage/Mage/src/mage/util/CircularList.java
2010-05-17 03:08:18 +00:00

458 lines
9 KiB
Java

/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package mage.util;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.locks.ReentrantLock;
/**
* a thread-safe circular list
*
* @author BetaSteward_at_googlemail.com
*/
public class CircularList<E> implements List<E>, Iterable<E>, Serializable {
protected List<E> list = new ArrayList<E>();
protected final ReentrantLock lock = new ReentrantLock();
protected int modCount;
protected int index;
/**
* Inserts an element into the current position
*/
@Override
public boolean add(E e) {
list.add(this.index, e);
return true;
}
@Override
public void add(int index, E element) {
lock.lock();
try {
list.add(index, element);
modCount++;
}
finally {
lock.unlock();
}
}
/**
*
* @param e the element to set as current
* @return true if element e exists and index was set
*/
public boolean setCurrent(E e) {
if (list.contains(e)) {
this.index = list.indexOf(e);
return true;
}
return false;
}
/**
* Retrieves the element at the current position
*/
public E get() {
return list.get(this.index);
}
@Override
public E get(int index) {
return list.get(index);
}
/**
* Returns the next element in the list
*
* @return the next element in the list
*/
public E getNext() {
return list.get(incrementPointer());
}
/**
* Returns the previous element in the list
*
* @return the previous element in the list
*/
public E getPrevious() {
return list.get(decrementPointer());
}
/**
* Removes the current element from the list
*
* @return <tt>true</tt> is the item was successfully removed
*/
public boolean remove() {
return this.remove(get());
}
@Override
public E remove(int index) {
lock.lock();
try {
E ret = list.remove(index);
checkPointer();
modCount++;
return ret;
}
finally {
lock.unlock();
}
}
@Override
public boolean remove(Object o) {
lock.lock();
try {
boolean ret = list.remove(o);
checkPointer();
modCount++;
return ret;
}
finally {
lock.unlock();
}
}
private int incrementPointer() {
lock.lock();
try {
index = incrementListPointer(index);
return index;
}
finally {
lock.unlock();
}
}
private int incrementListPointer(int index) {
index++;
if (index >= list.size())
index = 0;
return index;
}
private int decrementPointer() {
lock.lock();
try {
index = decrementListPointer(index);
return index;
}
finally {
lock.unlock();
}
}
private int decrementListPointer(int index) {
index--;
if (index < 0)
index = list.size() - 1;
return index;
}
/**
* This method should only be called from a locked method
* thus it is not necessary to lock from this method
*/
private int checkPointer() {
if (index > list.size()) {
index = list.size() - 1;
}
else if (index < 0)
index = 0;
return index;
}
@Override
public int size() {
return list.size();
}
@Override
public boolean isEmpty() {
return list.isEmpty();
}
@Override
public boolean contains(Object o) {
return list.contains(o);
}
@Override
public Object[] toArray() {
return list.toArray();
}
@Override
public <T> T[] toArray(T[] a) {
return list.toArray(a);
}
public List<E> toList() {
return list;
}
@Override
public boolean containsAll(Collection<?> c) {
return list.containsAll(c);
}
@Override
public boolean addAll(Collection<? extends E> c) {
return this.addAll(this.index, c);
}
@Override
public boolean addAll(int index, Collection<? extends E> c) {
lock.lock();
try {
modCount++;
return list.addAll(index, c);
}
finally {
lock.unlock();
}
}
@Override
public boolean removeAll(Collection<?> c) {
lock.lock();
try {
boolean ret = list.removeAll(c);
modCount++;
checkPointer();
return ret;
}
finally {
lock.unlock();
}
}
@Override
public boolean retainAll(Collection<?> c) {
lock.lock();
try {
boolean ret = list.retainAll(c);
modCount++;
checkPointer();
return ret;
}
finally {
lock.unlock();
}
}
@Override
public void clear() {
lock.lock();
try {
list.clear();
modCount++;
index = 0;
}
finally {
lock.unlock();
}
}
@Override
public E set(int index, E element) {
lock.lock();
try {
modCount++;
return list.set(index, element);
}
finally {
lock.unlock();
}
}
public E set(E element) {
return this.set(this.index, element);
}
@Override
public int indexOf(Object o) {
return list.indexOf(o);
}
@Override
public int lastIndexOf(Object o) {
return list.lastIndexOf(o);
}
@Override
public List<E> subList(int fromIndex, int toIndex) {
return list.subList(fromIndex, toIndex);
}
@Override
public Iterator<E> iterator() {
return new CircularIterator<E>();
}
@Override
public ListIterator<E> listIterator() {
return new CircularListIterator<E>();
}
@Override
public ListIterator<E> listIterator(int index) {
return new CircularListIterator<E>(index);
}
private class CircularIterator<E> implements Iterator<E> {
int cursor;
int lastIndex;
int curModCount;
boolean hasMoved = false;
private CircularIterator() {
curModCount = modCount;
cursor = index;
lastIndex = cursor;
}
@Override
public boolean hasNext() {
if (!hasMoved && size() > 0)
return true;
return cursor != lastIndex;
}
@Override
public E next() {
if (!this.hasNext())
throw new IllegalStateException();
if (curModCount != modCount)
throw new ConcurrentModificationException();
E data = (E) list.get(cursor);
cursor = incrementListPointer(cursor);
hasMoved = true;
return data;
}
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
private class CircularListIterator<E> implements ListIterator<E> {
int cursor;
int lastIndex;
int firstIndex;
int curModCount;
boolean hasMoved = false;
private CircularListIterator() {
this(index);
}
private CircularListIterator(int index) {
curModCount = modCount;
cursor = index;
firstIndex = index;
lastIndex = index;
}
public boolean hasNext() {
if (!hasMoved && size() > 0)
return true;
return cursor != lastIndex;
}
public E next() {
if (!this.hasNext())
throw new IllegalStateException();
if (curModCount != modCount)
throw new ConcurrentModificationException();
E data = (E) list.get(cursor);
cursor = incrementListPointer(cursor);
hasMoved = true;
return data;
}
public boolean hasPrevious() {
if (!hasMoved && size() > 0)
return true;
return cursor != firstIndex;
}
public E previous() {
if (!this.hasPrevious())
throw new IllegalStateException();
if (curModCount != modCount)
throw new ConcurrentModificationException();
cursor = decrementListPointer(cursor);
hasMoved = true;
return (E) list.get(cursor);
}
public int nextIndex() {
if (this.hasNext())
return incrementListPointer(cursor);
return list.size();
}
public int previousIndex() {
if (this.hasPrevious())
return decrementListPointer(cursor);
return -1;
}
public void remove() {
throw new UnsupportedOperationException("Not supported yet.");
}
public void set(E arg0) {
throw new UnsupportedOperationException("Not supported yet.");
}
public void add(E arg0) {
throw new UnsupportedOperationException("Not supported yet.");
}
}
}