001: //Copyright (c) Corporation for National Research Initiatives
002: package org.python.core;
003:
004: import java.io.Serializable;
005: import java.util.AbstractList;
006: import java.util.Collection;
007: import java.util.Iterator;
008:
009: /**
010: * <CODE>java.util.List</CODE> implementation using an underlying PyObject
011: * array for higher performance. Jython should use the following methods
012: * where possible, instead of their <CODE>List</CODE> counterparts:
013: * <UL>
014: * <LI>pyadd(int, PyObject)</LI>
015: * <LI>pyadd(PyObject)</LI>
016: * <LI>pyset(PyObject)</LI>
017: * <LI>pyget()</LI>
018: * </UL>
019: * @author Clark Updike
020: */
021: public class PyObjectList
022: //RandomAcces is jdk 1.4 -- restore when 1.4 becomes the min
023: extends AbstractList implements /*RandomAccess,*/Cloneable,
024: Serializable {
025:
026: /* Design note:
027: * This class let's PySequenceList implement java.util.List by delegating
028: * to an instance of this. The major distinction is that the backing array
029: * is PyObject[], not Object[] (as you'd get by delegating to ArrayList).
030: * There are 2 major benefits: 1) A lot of casting can be avoided
031: * internally (although use of PySequenceList descendants as java
032: * collections does involve some casting); 2) PySequenceList descendants
033: * can still do bulk array operations, allowing better performance and
034: * reuse of much of the pre-collections bulk operation implementation.
035: */
036:
037: /**
038: * Provides mutable operations on a PyObject[] array, including features
039: * that help with implementing java.util.List.
040: */
041: protected PyObjectArray array;
042:
043: public PyObjectList() {
044: array = new PyObjectArray();
045: }
046:
047: public PyObjectList(PyObject[] pyObjArr) {
048: array = new PyObjectArray(pyObjArr);
049: array.baseArray = pyObjArr;
050: }
051:
052: public PyObjectList(Collection c) {
053: array = new PyObjectArray();
054: array.appendArray(c.toArray());
055: }
056:
057: public PyObjectList(int size) {
058: array = new PyObjectArray(size);
059: }
060:
061: /**
062: * For internal jython usage, use {@link #pyadd(int, PyObject)}.
063: */
064: public void add(int index, Object element) {
065: array.add(index, Py.java2py(element));
066: modCount += array.getModCountIncr();
067: }
068:
069: public void pyadd(int index, PyObject element) {
070: array.add(index, element);
071: modCount += array.getModCountIncr();
072: }
073:
074: /**
075: * For internal jython usage, use {@link #pyadd(PyObject)}.
076: */
077: public boolean add(Object o) {
078: array.add(Py.java2py(o));
079: modCount += array.getModCountIncr();
080: return true;
081: }
082:
083: public boolean pyadd(PyObject o) {
084: array.add(o);
085: modCount += array.getModCountIncr();
086: return true;
087: }
088:
089: public Object clone() {
090: try {
091: PyObjectList tol = (PyObjectList) super .clone();
092: tol.array = (PyObjectArray) array.clone();
093: modCount = 0;
094: return tol;
095: } catch (CloneNotSupportedException eCNSE) {
096: throw new InternalError(
097: "Unexpected CloneNotSupportedException.\n"
098: + eCNSE.getMessage());
099: }
100: }
101:
102: public boolean equals(Object o) {
103: if (o instanceof PyObjectList) {
104: return array.equals(((PyObjectList) o).array);
105: }
106: return false;
107: }
108:
109: public int hashCode() {
110: return array.hashCode();
111: }
112:
113: /**
114: * Use <code>pyget(int)</code> for internal jython usage.
115: */
116: public Object get(int index) {
117: PyObject obj = array.get(index);
118: return obj.__tojava__(Object.class);
119: }
120:
121: PyObject pyget(int index) {
122: return array.get(index);
123: }
124:
125: public Object remove(int index) {
126: modCount++;
127: Object existing = array.get(index);
128: array.remove(index);
129: return existing;
130: }
131:
132: public void remove(int start, int stop) {
133: modCount++;
134: array.remove(start, stop);
135: }
136:
137: /**
138: * Use <code>pyset(int, PyObject)</code> for internal jython usage.
139: */
140: public Object set(int index, Object element) {
141: return array.set(index, Py.java2py(element)).__tojava__(
142: Object.class);
143: }
144:
145: PyObject pyset(int index, PyObject element) {
146: return array.set(index, element);
147: }
148:
149: public int size() {
150: return array.getSize();
151: }
152:
153: public boolean addAll(Collection c) {
154: return addAll(size(), c);
155: }
156:
157: public boolean addAll(int index, Collection c) {
158: if (c instanceof PySequenceList) {
159: PySequenceList cList = (PySequenceList) c;
160: PyObject[] cArray = cList.getArray();
161: int cOrigSize = cList.size();
162: array.makeInsertSpace(index, cOrigSize);
163: array.replaceSubArray(index, index + cOrigSize, cArray, 0,
164: cOrigSize);
165: } else {
166: // need to use add to convert anything pulled from a collection
167: // into a PyObject
168: for (Iterator i = c.iterator(); i.hasNext();) {
169: add(i.next());
170: }
171: }
172: return c.size() > 0;
173: }
174:
175: /**
176: * Get the backing array. The array should generally not be modified.
177: * To get a copy of the array, see {@link #toArray()} which returns a copy.
178: *
179: * @return backing array object
180: */
181: protected PyObject[] getArray() {
182: return (PyObject[]) array.getArray();
183: }
184:
185: void ensureCapacity(int minCapacity) {
186: array.ensureCapacity(minCapacity);
187: }
188:
189: void replaceSubArray(int destStart, int destStop, Object srcArray,
190: int srcStart, int srcStop) {
191: array.replaceSubArray(destStart, destStop, srcArray, srcStart,
192: srcStop);
193: }
194:
195: void setSize(int count) {
196: array.setSize(count);
197: }
198: }
|