package aliview.sequences;
import java.util.BitSet;
import org.apache.log4j.Logger;
public class DefaultSequenceSelectionModel implements SequenceSelectionModel {
private static final Logger logger = Logger.getLogger(DefaultSequenceSelectionModel.class);
BitSet bitSelection;
boolean allSelected;
public boolean isSelected(int n) {
if(allSelected){
return true;
}
if(bitSelection == null){
return false;
}else{
return bitSelection.get(n);
}
}
private BitSet createNewSelection() {
allSelected = false;
return new BitSet();
}
public void clearAll() {
//logger.info("clearAll");
bitSelection = null;
allSelected = false;
}
public void selectAll() {
clearAll();
allSelected = true;
}
public int getFirstSelectedPosition() {
if(allSelected){
return 0;
}
if(bitSelection == null){
return -1;
}else{
return bitSelection.nextSetBit(0);
}
}
public int getLastSelectedPosition(int seqLength) {
if(allSelected){
return seqLength - 1;
}
if(bitSelection == null){
return -1;
}else{
// last bit in bitset is always set (autoshrink)
return bitSelection.length() - 1;
}
}
public boolean hasSelection() {
if(allSelected){
return true;
}
if(bitSelection == null){
return false;
}else{
return !bitSelection.isEmpty();
}
}
public int[] getSelectedPositions(int startIndex, int endIndex) {
if(allSelected){
int[] pos = new int[endIndex - startIndex + 1];
for(int n = 0; n<pos.length; n++){
pos[n] = n;
}
return pos;
}
if(bitSelection == null){
return new int[0];
}
int[] pos = new int[countSelectedPositions(startIndex, endIndex)];
int index = 0;
for(int i = bitSelection.nextSetBit(startIndex); i >= 0 && i <= endIndex; i = bitSelection.nextSetBit(i+1)) {
pos[index] = i;
index++;
}
return pos;
}
public int countPositionsUntilSelectedCount(int selectedCount) {
if(allSelected){
return selectedCount-1;
}
if(bitSelection == null){
logger.info("no bit selection");
return -1;
}else{
int index = -1;
int nCount = 0;
for (int i = bitSelection.nextSetBit(0); i >= 0 && i <= bitSelection.length(); i = bitSelection.nextSetBit(i+1)) {
// logger.info("i" + i);
nCount ++;
if(nCount == selectedCount){
index = i;
break;
}
}
return index;
}
}
public int countSelectedPositions(int startIndex, int endIndex) {
if(allSelected){
return endIndex - startIndex + 1;
}
if(bitSelection == null){
return 0;
}else{
int nCount = 0;
for (int i = bitSelection.nextSetBit(startIndex); i >= 0 && i <= endIndex; i = bitSelection.nextSetBit(i+1)) {
nCount ++;
}
return nCount;
}
}
public void clearSelectionAt(int n) {
clearSelection(n, n, false);
}
public void clearSelection(int startIndex, int endIndex, boolean clearFirst){
if(clearFirst){
clearAll();
}
if(bitSelection == null){
return; // already clear
}
bitSelection.set(startIndex, endIndex + 1, false); // bitselection end index is exclusive
}
public void setSelectionAt(int n){
setSelection(n, n, false);
}
public void setSelection(int startIndex, int endIndex, boolean clearFirst){
if(clearFirst){
clearAll();
}
if(bitSelection == null){
bitSelection = createNewSelection();
}
bitSelection.set(startIndex, endIndex + 1, true); // bitselection end index is exclusive
}
public void rightPad(int length) {
// nothing need to be done
}
public void leftPad(int length) {
if(hasSelection() && allSelected == false){
for(int n = 0; n < length; n++){
insertNewPosAt(0);
}
}
}
public void removePosition(int index) {
if(hasSelection() && allSelected == false){
for(int n = index; n < bitSelection.length(); n++){
bitSelection.set(n,bitSelection.get(n+1));
}
}
}
public void insertNewPosAt(int index) {
if(hasSelection() && allSelected == false){
for(int n = bitSelection.length(); n >= index; n--){
bitSelection.set(n + 1,bitSelection.get(n));
}
bitSelection.set(index,false);
}
}
public boolean isAllSelected() {
return allSelected;
}
public void invertSelection(int length) {
// Full selection
if(allSelected){
clearAll();
}else if(hasSelection() == false){
selectAll();
}
// partial selection
if(hasSelection() && allSelected != true){
logger.info("partial");
bitSelection.flip(0, length);
}
}
}