/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.util;
import java.util.AbstractList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
/**
* This list remains sorted
*
* @author jcompagner
*/
public class SortedList<E> extends AbstractList<E>
{
protected int _size;
protected Object[] _data;
protected Comparator _comp;
private int _index;
public SortedList()
{
this(COMPARABLE_COMPARATOR, 25);
}
public SortedList(int initialSize)
{
this(COMPARABLE_COMPARATOR, initialSize);
}
public SortedList(Collection< ? extends E> collection)
{
this(COMPARABLE_COMPARATOR, collection);
}
public SortedList(Comparator< ? > comp)
{
this(comp, 25);
}
public SortedList(Comparator< ? > comp, int initialSize)
{
_comp = comp;
_data = new Object[initialSize];
}
public SortedList(Comparator< ? > comp, Collection< ? extends E> collection)
{
_comp = comp;
_data = new Object[collection.size() + 25];
addAll(collection);
}
/**
* @see java.util.List#get(int)
*/
@Override
public E get(int index)
{
return (E)_data[index];
}
/**
* @see java.util.Collection#size()
*/
@Override
public int size()
{
return _size;
}
/**
* @see java.util.Collection#add(java.lang.Object)
*/
@Override
public boolean add(E o)
{
int index = indexOfIntern(o);
if (index < 0) index = -(index + 1);
try
{
if (index != _size)
{
System.arraycopy(_data, index, _data, index + 1, _size - index);
}
_data[index] = o;
}
catch (ArrayIndexOutOfBoundsException ex)
{
Object[] data = new Object[_size + 25];
System.arraycopy(_data, 0, data, 0, index);
System.arraycopy(_data, index, data, index + 1, _size - index);
data[index] = o;
_data = data;
}
_index = index;
_size++;
return true;
}
public void addAll(Iterator< ? extends E> it)
{
while (it.hasNext())
{
add(it.next());
}
}
@Override
public boolean addAll(Collection< ? extends E> c)
{
Iterator< ? extends E> it = c.iterator();
boolean retval = it.hasNext();
addAll(it);
return retval;
}
public int getInsertIndex()
{
return _index;
}
@Override
public int indexOf(Object o)
{
int index = indexOfIntern(o);
return index < 0 ? -1 : index;
}
/**
* can return number lower then -1!!!
*/
protected int indexOfIntern(Object o)
{
int low = 0;
int high = _size - 1;
while (low <= high)
{
int mid = (low + high) >> 1;
E midVal = (E)_data[mid];
int cmp = _comp.compare(midVal, o);
if (cmp < 0) low = mid + 1;
else if (cmp > 0) high = mid - 1;
else return mid; // key found
}
return -(low + 1);
}
/**
* @see java.util.Collection#contains(java.lang.Object)
*/
@Override
public boolean contains(Object o)
{
return indexOfIntern(o) >= 0;
}
/**
* @see java.util.List#remove(int)
*/
@Override
public E remove(int index)
{
if (index >= _size || index < 0) throw new ArrayIndexOutOfBoundsException("index greater than size or below zero for remove " + index); //$NON-NLS-1$
E data = (E)_data[index];
System.arraycopy(_data, index + 1, _data, index, _size - index - 1);
_size--;
_data[_size] = null;
return data;
}
/**
* @see java.util.Collection#remove(java.lang.Object)
*/
@Override
public boolean remove(Object o)
{
int index = indexOfIntern(o);
if (index >= 0) remove(index);
return index >= 0;
}
/*
* (non-Javadoc)
*
* @see java.util.AbstractList#clear()
*/
@Override
public void clear()
{
_size = 0;
_data = new Object[_data.length];
}
public static final Comparator<Object> COMPARABLE_COMPARATOR = new ComparableComparator();
public static class ComparableComparator implements Comparator<Object>
{
/*
* @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
*/
public int compare(Object o1, Object o2)
{
return ((Comparable)o1).compareTo(o2);
}
}
}