/*******************************************************************************
 * 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 Vector extends AbstractList {
	
	protected int capacityIncrement;
	
	protected int elementCount;
	
	protected Object[] elementData;

public Vector() {
	this(10);
}

public Vector(int initialCapacity) {
	this(initialCapacity, 0);
}

public Vector(int initialCapacity, int capacityIncrement) {
	if (initialCapacity < 0) throw new IllegalArgumentException();
	elementData = new Object[initialCapacity];
	this.capacityIncrement = capacityIncrement > 0 ? capacityIncrement : 0;
}

public void addElement(Object obj) {
	ensureCapacity(elementCount + 1);
	elementData[elementCount++] = obj;
}

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 int capacity() {
	return elementData.length;
}

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

public void copyInto(Object[] anArray) {
	System.arraycopy(elementData, 0, anArray, 0, elementCount);
}

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

public Enumeration elements() {
	return new Enumeration() {
		int pos;
		
		public boolean hasMoreElements() {
			return pos < elementCount;
		}
		
		public Object nextElement() {
			if (pos >= elementCount) throw new NoSuchElementException();
			return elementData[pos++];
		}
	};
}

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 Object firstElement() {
	if (elementCount == 0) throw new NoSuchElementException();
	return elementData[0];
}

public Object get(int index) {
	return elementAt(index);
}

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

public int indexOf(Object elem) {
	return indexOf(elem, 0);
}

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

public int insertElementAt(Object obj, int index) {
	if (index < 0 || index >= elementCount) throw new ArrayIndexOutOfBoundsException();
	ensureCapacity(elementCount + 1);
	Array array = getArray();
	array.splice(index, 0, obj);
	elementCount++;
	return 0;
}

public boolean isEmpty() {
	return elementCount == 0;
}

public Object lastElement() {
	if (elementCount == 0) throw new NoSuchElementException();
	return elementData[elementCount - 1];
}

public int lastIndexOf(Object elem) {
	return lastIndexOf(elem, elementCount - 1);
}

public int lastIndexOf(Object elem, int index) {
	if (index >= elementCount) throw new IndexOutOfBoundsException();
	if (elem == null) {
		for (int i=index; i>=0; i--) {
			if (elementData[i] == null) return i;
		}
	} else {
		for (int i=index; i>=0; i--) {
			if (elem.equals(elementData[i])) 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 void removeAllElements() {
	for (int i = 0; i < elementCount; i++) {
		elementData[i] = null;
	}
	elementCount = 0;
}

public boolean removeElement(Object elem) {
	int index = indexOf(elem);
	if (index != -1) {
		removeElementAt(index);
		return true;
	}
	return false;
}

public void removeElementAt(int index) {
	if (index < 0 || index >= elementCount) throw new ArrayIndexOutOfBoundsException();
	Array array = getArray();
	array.splice(index, 1);
	array.length++;
	elementCount--;
}

public void setElementAt(Object elem, int index) {
	if (index >= elementCount) throw new ArrayIndexOutOfBoundsException();
	elementData[index] = elem;
}

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

public void setSize(int newSize) {
	if (newSize == elementCount) return;
	if (newSize > elementCount) {
		ensureCapacity(newSize);
	} else {
		for (int i = newSize; i < elementCount; i++) {
			elementData[i] = null;
		}
	}
	elementCount = newSize;
}

public int size() {
	return elementCount;
}

public String toString() {
	StringBuffer buffer = new StringBuffer();
	buffer.append("[");
	for (int i = 0; i < elementCount; i++) {
		if (i != 0) buffer.append(", ");
		buffer.append(elementData[i]);
	}
	buffer.append("]");
	return buffer.toString();
}

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

}