001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package java.util;
017:
018: import com.google.gwt.core.client.JavaScriptObject;
019: import com.google.gwt.lang.Array;
020:
021: import java.io.Serializable;
022:
023: /**
024: * Resizeable array implementation of the List interface. <a
025: * href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/ArrayList.html">[Sun
026: * docs]</a>
027: *
028: * <p>
029: * This implementation differs from JDK 1.5 <code>ArrayList</code> in terms of
030: * capacity management. There is no speed advantage to pre-allocating array
031: * sizes in JavaScript, so this implementation does not include any of the
032: * capacity and "growth increment" concepts in the standard ArrayList class.
033: * Although <code>ArrayList(int)</code> accepts a value for the initial
034: * capacity of the array, this constructor simply delegates to
035: * <code>ArrayList()</code>. It is only present for compatibility with JDK
036: * 1.5's API.
037: * </p>
038: *
039: * @param <E> the element type.
040: */
041: public class ArrayList<E> extends AbstractList<E> implements List<E>,
042: Cloneable, RandomAccess, Serializable {
043:
044: private static native void addImpl(JavaScriptObject array,
045: int index, Object o) /*-{
046: array.splice(index, 0, o);
047: }-*/;
048:
049: private static boolean equals(Object a, Object b) {
050: return a == b || (a != null && a.equals(b));
051: }
052:
053: private static native <E> E getImpl(JavaScriptObject array,
054: int index) /*-{
055: return array[index];
056: }-*/;
057:
058: private static native void removeRangeImpl(JavaScriptObject array,
059: int index, int count) /*-{
060: array.splice(index, count);
061: }-*/;
062:
063: private static native <E> void setImpl(JavaScriptObject array,
064: int index, E o) /*-{
065: array[index] = o;
066: }-*/;
067:
068: private static native void setSizeImpl(JavaScriptObject array,
069: int newSize) /*-{
070: array.length = newSize;
071: }-*/;
072:
073: /**
074: * This field holds a JavaScript array.
075: */
076: private transient JavaScriptObject array;
077:
078: /**
079: * The size of the array.
080: */
081: private int size;
082:
083: {
084: clearImpl();
085: }
086:
087: public ArrayList() {
088: }
089:
090: public ArrayList(Collection<? extends E> c) {
091: addAll(c);
092: }
093:
094: /**
095: * There is no speed advantage to pre-allocating array sizes in JavaScript.
096: * This constructor is only present for compatibility with the JRE.
097: */
098: public ArrayList(int ignoredInitialCapacity) {
099: }
100:
101: @Override
102: public void add(int index, E o) {
103: if (index < 0 || index > size) {
104: indexOutOfBounds(index);
105: }
106: addImpl(array, index, o);
107: ++size;
108: }
109:
110: @Override
111: public boolean add(E o) {
112: setImpl(array, size++, o);
113: return true;
114: }
115:
116: @Override
117: public boolean addAll(Collection<? extends E> c) {
118: Iterator<? extends E> iter = c.iterator();
119: boolean changed = iter.hasNext();
120: while (iter.hasNext()) {
121: setImpl(array, size++, iter.next());
122: }
123: return changed;
124: }
125:
126: @Override
127: public void clear() {
128: clearImpl();
129: }
130:
131: public Object clone() {
132: return new ArrayList<E>(this );
133: }
134:
135: @Override
136: public boolean contains(Object o) {
137: return (indexOf(o) != -1);
138: }
139:
140: @Override
141: public E get(int index) {
142: if (index < 0 || index >= size) {
143: indexOutOfBounds(index);
144: }
145: return getImpl(array, index);
146: }
147:
148: @Override
149: public int indexOf(Object o) {
150: return indexOf(o, 0);
151: }
152:
153: @Override
154: public boolean isEmpty() {
155: return size == 0;
156: }
157:
158: @Override
159: public int lastIndexOf(Object o) {
160: return lastIndexOf(o, size() - 1);
161: }
162:
163: @Override
164: public E remove(int index) {
165: E previous = get(index);
166: removeRangeImpl(array, index, 1);
167: --size;
168: return previous;
169: }
170:
171: @Override
172: public boolean remove(Object o) {
173: int i = indexOf(o);
174: if (i == -1) {
175: return false;
176: }
177: remove(i);
178: return true;
179: }
180:
181: @Override
182: public E set(int index, E o) {
183: E previous = get(index);
184: setImpl(array, index, o);
185: return previous;
186: }
187:
188: @Override
189: public int size() {
190: return size;
191: }
192:
193: @Override
194: public List<E> subList(int fromIndex, int toIndex) {
195: // TODO(jat): implement
196: throw new UnsupportedOperationException(
197: "subList not implemented");
198: }
199:
200: /*
201: * Faster than the iterator-based implementation in AbstractCollection.
202: */
203: @Override
204: public <T> T[] toArray(T[] a) {
205: if (a.length < size) {
206: a = Array.clonify(a, size);
207: }
208: for (int i = 0; i < size; ++i) {
209: a[i] = getImpl(array, i);
210: }
211: if (a.length > size) {
212: a[size] = null;
213: }
214: return a;
215: }
216:
217: /**
218: * Currently ignored.
219: */
220: public void trimToSize() {
221: // TODO(jat): implement
222: }
223:
224: protected int indexOf(Object o, int index) {
225: if (index < 0) {
226: indexOutOfBounds(index);
227: }
228: for (; index < size; ++index) {
229: if (equals(o, getImpl(array, index))) {
230: return index;
231: }
232: }
233: return -1;
234: }
235:
236: protected int lastIndexOf(Object o, int index) {
237: if (index >= size) {
238: indexOutOfBounds(index);
239: }
240: for (; index >= 0; --index) {
241: if (equals(o, getImpl(array, index))) {
242: return index;
243: }
244: }
245: return -1;
246: }
247:
248: @Override
249: protected void removeRange(int fromIndex, int endIndex) {
250: if (fromIndex < 0 || fromIndex >= size) {
251: indexOutOfBounds(fromIndex);
252: }
253: if (endIndex < fromIndex || endIndex > size) {
254: indexOutOfBounds(endIndex);
255: }
256: int count = endIndex - fromIndex;
257: removeRangeImpl(array, fromIndex, count);
258: size -= count;
259: }
260:
261: /**
262: * This function sets the size of the array, and is used by Vector.
263: */
264: protected void setSize(int newSize) {
265: if (newSize < 0) {
266: indexOutOfBounds(newSize);
267: }
268: setSizeImpl(array, newSize);
269: // null fill any new slots if size < newSize
270: for (; size < newSize; ++size) {
271: setImpl(array, size, null);
272: }
273: // assignment necessary when size > newSize
274: size = newSize;
275: }
276:
277: private void clearImpl() {
278: array = JavaScriptObject.createArray();
279: size = 0;
280: }
281: }
|