/*******************************************************************************
 * Copyright (c) 2000, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package java.util;

import intrinsic.Array;

public class ArrayList extends AbstractList implements RandomAcess {

	int capacityIncrement;
	int elementCount;
	Object[] elementData;
	
public ArrayList() {
	this(10);
}

public ArrayList(Collection c) {
	this(c.size() + c.size() / 10);
	Iterator iterator = c.iterator();
	while (iterator.hasNext()) {
		add(iterator.next());
	}
}

public ArrayList(int initialCapacity) {
	if (initialCapacity < 0) throw new IllegalArgumentException();
	elementData = new Object[initialCapacity];
}

public void ensureCapacity(int minCapacity) {
	int len = elementData.length;
	if (len >= minCapacity) return;
	int newCapacity = capacityIncrement <= 0 ? len * 2 : len + capacityIncrement;
	getArray().length = minCapacity > newCapacity ? minCapacity : newCapacity;
}

public void add(int index, Object element) {
	if (index < 0 || index > elementCount) throw new IndexOutOfBoundsException();
	ensureCapacity(elementCount + 1);
	if (index != elementCount) {
		System.arraycopy(elementData, index, elementData, index + 1, elementCount - index);
	}
	elementCount++;
	elementData[index] = element;
}

public void clear() {
	for (int i = 0; i < elementCount; i++) {
		elementData[i] = null;
	}
	elementCount = 0;
}

public boolean contains(Object o) {
	for (int i = 0; i < elementCount; i++) {
		Object element = elementData[i];
		if (o == null ? element == null : o.equals(element)) {
			return true;
		}
	}
	return false;
}

private native Array getArray()/*{
	return elementData.array as Array;
}*/;

public Object get(int index) {
	if (index >= elementCount) throw new ArrayIndexOutOfBoundsException();
	return elementData[index];
}

public int indexOf(Object o) {
	if (o == null) {
		for (int i = 0; i < elementCount; i++) {
			Object element = elementData[i];
			if (element == null) {
				return i;
			}
		}
	} else {
		for (int i = 0; i < elementCount; i++) {
			Object element = elementData[i];
			if (o.equals(element)) {
				return i;
			}
		}
	}
	return -1;
}

public int lastIndexOf(Object o) {
	if (o == null) {
		for (int i = elementCount - 1; i >= 0; i--) {
			Object element = elementData[i];
			if (element == null) {
				return i;
			}
		}
	} else {
		for (int i = elementCount - 1; i >= 0; i--) {
			Object element = elementData[i];
			if (o.equals(element)) {
				return i;
			}
		}
	}
	return -1;
}

public Object remove(int index) {
	if (index < 0 || index > elementCount) throw new IndexOutOfBoundsException();
	Object result = elementData[index];
	if (index != elementCount) {
		System.arraycopy(elementData, index + 1, elementData, index, elementCount - index - 1);
	} else {
		elementData[index] = null;
	}
	elementCount--;
	return result;
}

public Object set(int index, Object element) {
	if (index >= elementCount) throw new ArrayIndexOutOfBoundsException();
	Object result = elementData[index];
	elementData[index] = element;
	return result;
}

public int size() {
	return elementCount;
}

public Object[] toArray() {
	return toArray(new Object[elementCount]);
}

public Object[] toArray(Object[] a) {
	if (a.length < elementCount) a = (Object[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), elementCount);
	System.arraycopy(elementData, 0, a, 0, elementCount);
	return a;
}

public void trimToSize() {
	getArray().length = elementCount;
}

}
