/*
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.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.RandomAccess;
import com.servoy.j2db.server.annotations.TerracottaInstrumentedClass;
/**
* This class is resistent to inserts, adds and gets on positions not defined, and it uses the Utils.equalsObject(...) to perform equals on objects (which is
* more data compatible).<br>
* <br>
* Changed the class to wrap an ArrayList instance instead of extending ArrayList because it is shared with Terracotta when running a cluster of servers and it would no be "portable" because it would extend
* a "logically managed" class and override some of it's methods.
*
* @author jblok
*/
@TerracottaInstrumentedClass
public class SafeArrayList<E> implements Collection<E>, List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private int initialCapacity;
private final ArrayList<E> list;
public SafeArrayList()
{
list = new ArrayList<E>(10);
}
public SafeArrayList(int initialCapacity)
{
list = new ArrayList<E>(initialCapacity);
this.initialCapacity = initialCapacity;
}
public SafeArrayList(Collection< ? extends E> c)
{
list = new ArrayList<E>(c);
initialCapacity = (int)Math.min((c.size() * 110L) / 100, Integer.MAX_VALUE);
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#clone()
*/
@SuppressWarnings("unchecked")
@Override
public SafeArrayList<E> clone()
{
return new SafeArrayList<E>((Collection< ? extends E>)list.clone());
}
public E get(int index)
{
if (index >= 0 && index < list.size())
{
return list.get(index);
}
return null;
}
public E remove(int index)
{
if (index >= 0 && index < list.size())
{
return list.remove(index);
}
return null;
}
public void add(int index, E obj)
{
int s = list.size();
if (index > s)
{
for (int fill = s; fill < index; fill++)
{
list.add(null);
}
}
if (index == s)
{
list.add(obj);
}
else
{
list.add(index, obj);
}
}
public E set(int index, E obj)
{
int s = list.size();
if (index == s)
{
list.add(obj);
return null;
}
if (index > s)
{
for (int fill = s; fill <= index; fill++)
{
list.add(null);
}
}
if (obj == null && index == s - 1 && index >= initialCapacity)
{
return remove(index);
}
else
{
return list.set(index, obj);
}
}
/**
* Searches for the first occurence of the given argument, testing for equality using the <tt>equals</tt> method.
*
* @param elem an object.
* @return the index of the first occurrence of the argument in this list; returns <tt>-1</tt> if the object is not found.
* @see Object#equals(Object)
*/
public int indexOf(Object elem)
{
if (elem == null)
{
for (int i = 0; i < list.size(); i++)
{
if (get(i) == null)
{
return i;
}
}
}
else
{
for (int i = 0; i < list.size(); i++)
{
if (Utils.equalObjects(elem, get(i)))
{
return i;
}
}
}
return -1;
}
/**
* Returns the index of the last occurrence of the specified object in this list.
*
* @param elem the desired element.
* @return the index of the last occurrence of the specified object in this list; returns -1 if the object is not found.
*/
public int lastIndexOf(Object elem)
{
if (elem == null)
{
for (int i = list.size() - 1; i >= 0; i--)
{
if (get(i) == null)
{
return i;
}
}
}
else
{
for (int i = list.size() - 1; i >= 0; i--)
{
if (Utils.equalObjects(elem, get(i)))
{
return i;
}
}
}
return -1;
}
public boolean add(E o)
{
return list.add(o);
}
public boolean addAll(Collection< ? extends E> c)
{
return list.addAll(c);
}
public void clear()
{
list.clear();
}
public boolean contains(Object o)
{
return list.contains(o);
}
public boolean containsAll(Collection< ? > c)
{
return list.containsAll(c);
}
public boolean isEmpty()
{
return list.isEmpty();
}
public Iterator<E> iterator()
{
return list.iterator();
}
public boolean remove(Object o)
{
return list.remove(o);
}
public boolean removeAll(Collection< ? > c)
{
return list.removeAll(c);
}
public boolean retainAll(Collection< ? > c)
{
return list.retainAll(c);
}
public int size()
{
return list.size();
}
public Object[] toArray()
{
return list.toArray();
}
public <T> T[] toArray(T[] a)
{
return list.toArray(a);
}
public boolean addAll(int index, Collection< ? extends E> c)
{
return list.addAll(index, c);
}
public ListIterator<E> listIterator()
{
return list.listIterator();
}
public ListIterator<E> listIterator(int index)
{
return list.listIterator(index);
}
public List<E> subList(int fromIndex, int toIndex)
{
return list.subList(fromIndex, toIndex);
}
@Override
public String toString()
{
return list.toString();
}
}