//Copyright (c) Corporation for National Research Initiatives
package org.python.core;
import java.io.Serializable;
import java.util.AbstractList;
import java.util.Collection;
import java.util.Iterator;
/**
* <CODE>java.util.List</CODE> implementation using an underlying PyObject
* array for higher performance. Jython should use the following methods
* where possible, instead of their <CODE>List</CODE> counterparts:
* <UL>
* <LI>pyadd(int, PyObject)</LI>
* <LI>pyadd(PyObject)</LI>
* <LI>pyset(PyObject)</LI>
* <LI>pyget()</LI>
* </UL>
* @author Clark Updike
*/
public class PyObjectList
//RandomAcces is jdk 1.4 -- restore when 1.4 becomes the min
extends AbstractList implements /*RandomAccess,*/Cloneable, Serializable {
/* Design note:
* This class let's PySequenceList implement java.util.List by delegating
* to an instance of this. The major distinction is that the backing array
* is PyObject[], not Object[] (as you'd get by delegating to ArrayList).
* There are 2 major benefits: 1) A lot of casting can be avoided
* internally (although use of PySequenceList descendants as java
* collections does involve some casting); 2) PySequenceList descendants
* can still do bulk array operations, allowing better performance and
* reuse of much of the pre-collections bulk operation implementation.
*/
/**
* Provides mutable operations on a PyObject[] array, including features
* that help with implementing java.util.List.
*/
protected PyObjectArray array;
public PyObjectList() {
array = new PyObjectArray();
}
public PyObjectList(PyObject[] pyObjArr) {
array = new PyObjectArray(pyObjArr);
array.baseArray = pyObjArr;
}
public PyObjectList(Collection c) {
array = new PyObjectArray();
array.appendArray(c.toArray());
}
public PyObjectList(int size) {
array = new PyObjectArray(size);
}
/**
* For internal jython usage, use {@link #pyadd(int, PyObject)}.
*/
public void add(int index, Object element) {
array.add(index, Py.java2py(element));
modCount += array.getModCountIncr();
}
public void pyadd(int index, PyObject element) {
array.add(index, element);
modCount += array.getModCountIncr();
}
/**
* For internal jython usage, use {@link #pyadd(PyObject)}.
*/
public boolean add(Object o) {
array.add(Py.java2py(o));
modCount += array.getModCountIncr();
return true;
}
public boolean pyadd(PyObject o) {
array.add(o);
modCount += array.getModCountIncr();
return true;
}
public Object clone() {
try {
PyObjectList tol = (PyObjectList) super.clone();
tol.array = (PyObjectArray) array.clone();
modCount = 0;
return tol;
} catch (CloneNotSupportedException eCNSE) {
throw new InternalError("Unexpected CloneNotSupportedException.\n" + eCNSE.getMessage());
}
}
public boolean equals(Object o) {
if (o instanceof PyObjectList) {
return array.equals(((PyObjectList) o).array);
}
return false;
}
public int hashCode() {
return array.hashCode();
}
/**
* Use <code>pyget(int)</code> for internal jython usage.
*/
public Object get(int index) {
PyObject obj = array.get(index);
return obj.__tojava__(Object.class);
}
PyObject pyget(int index) {
return array.get(index);
}
public Object remove(int index) {
modCount++;
Object existing = array.get(index);
array.remove(index);
return existing;
}
public void remove(int start, int stop) {
modCount++;
array.remove(start, stop);
}
/**
* Use <code>pyset(int, PyObject)</code> for internal jython usage.
*/
public Object set(int index, Object element) {
return array.set(index, Py.java2py(element)).__tojava__(Object.class);
}
PyObject pyset(int index, PyObject element) {
return array.set(index, element);
}
public int size() {
return array.getSize();
}
public boolean addAll(Collection c) {
return addAll(size(), c);
}
public boolean addAll(int index, Collection c) {
if (c instanceof PySequenceList) {
PySequenceList cList = (PySequenceList) c;
PyObject[] cArray = cList.getArray();
int cOrigSize = cList.size();
array.makeInsertSpace(index, cOrigSize);
array.replaceSubArray(index, index + cOrigSize, cArray, 0, cOrigSize);
} else {
// need to use add to convert anything pulled from a collection
// into a PyObject
for (Iterator i = c.iterator(); i.hasNext();) {
add(i.next());
}
}
return c.size() > 0;
}
/**
* Get the backing array. The array should generally not be modified.
* To get a copy of the array, see {@link #toArray()} which returns a copy.
*
* @return backing array object
*/
protected PyObject[] getArray() {
return (PyObject[]) array.getArray();
}
void ensureCapacity(int minCapacity) {
array.ensureCapacity(minCapacity);
}
void replaceSubArray(int destStart, int destStop, Object srcArray, int srcStart, int srcStop) {
array.replaceSubArray(destStart, destStop, srcArray, srcStart, srcStop);
}
void setSize(int count) {
array.setSize(count);
}
}