/*
* Genoogle: Similar DNA Sequences Searching Engine and Tools. (http://genoogle.pih.bio.br)
* Copyright (C) 2008,2009,2010,2011,2012 Felipe Fernandes Albrecht (felipe.albrecht@gmail.com)
*
* For further information check the LICENSE file.
*/
package bio.pih.genoogle.util;
import bio.pih.genoogle.search.IndexRetrievedData;
import bio.pih.genoogle.search.RetrievedArea;
/**
* Circular Array used to store the {@link IndexRetrievedData} retrieved from the inverted index.
*
* @author albrecht
*
*/
public class CircularArrayList {
private RetrievedArea[] elementData;
private int head = 0, tail = 0;
private int size = 0;
private static final int DEFAULT_SIZE = 5;
/**
* Defaul constructor
*/
public CircularArrayList() {
this(DEFAULT_SIZE);
}
/**
* Constructor which specify the size of circular list. When the slot is occupied fully, it
* grows to 3/2 of the previous size.
*
* @param size
*/
public CircularArrayList(int size) {
elementData = new RetrievedArea[size];
}
public boolean isEmpty() {
return head == tail; // or size == 0
}
private void ensureCapacity(int minCapacity) {
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
int newCapacity = (oldCapacity * 3) / 2 + 1;
RetrievedArea newData[] = new RetrievedArea[newCapacity];
toArray(newData);
tail = size;
head = 0;
elementData = newData;
}
}
public int size() {
return size;
}
public RetrievedArea[] toArray(RetrievedArea a[]) {
if (head < tail) {
System.arraycopy(elementData, head, a, 0, tail - head);
} else {
System.arraycopy(elementData, head, a, 0, elementData.length - head);
System.arraycopy(elementData, 0, a, elementData.length - head, tail);
}
return a;
}
public void add(int queryPos, int sequencePos, int subSequenceLength) {
ensureCapacity(size + 1 + 1);
RetrievedArea retrievedArea = elementData[tail];
if (retrievedArea != null) {
retrievedArea.reset(queryPos, sequencePos, subSequenceLength);
} else {
assert (tail != elementData.length);
elementData[tail] = new RetrievedArea(queryPos, sequencePos, subSequenceLength);
}
tail = (tail + 1) % elementData.length;
size++;
assert ((head + size) % elementData.length == tail);
}
/**
* Set the informed position to this correct position.
* @param openedArea {@link RetrievedArea} which will be moved
* @param pos which should be moved
*/
public void rePos(RetrievedArea openedArea, int _pos) {
int pos = (_pos + head) % elementData.length;
assert (elementData[pos] == openedArea);
int prev = pos;
pos = (pos + 1) % elementData.length;
while (pos != tail && elementData[pos] != null
&& openedArea.getQueryAreaEnd() > elementData[pos].getQueryAreaEnd()) {
elementData[prev] = elementData[pos];
elementData[pos] = openedArea;
prev = pos;
pos = (pos + 1) % elementData.length;
}
}
/**
* Remove elements from the circular list.
*
* @param total
* quantity of elements which will be removed.
*/
public void removeElements(int total) {
size = size - total;
if (size == 0) {
tail = 0;
head = 0;
} else {
head = (head + total) % elementData.length;
}
assert ((head + size) % elementData.length == tail);
assert (size >= 0);
assert (tail >= 0);
assert (head >= 0);
}
public RetrievedArea get(int pos) {
if ((pos + 1) > size) {
return null;
}
RetrievedArea retrievedArea = elementData[(pos + head) % elementData.length];
return retrievedArea;
}
public void clear() {
head = tail = size = 0;
}
}