1/*
2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package javax.swing;
27
28import java.util.Vector;
29import java.util.Enumeration;
30
31import javax.swing.event.*;
32
33
34/**
35 * This class loosely implements the <code>java.util.Vector</code>
36 * API, in that it implements the 1.1.x version of
37 * <code>java.util.Vector</code>, has no collection class support,
38 * and notifies the <code>ListDataListener</code>s when changes occur.
39 * Presently it delegates to a <code>Vector</code>,
40 * in a future release it will be a real Collection implementation.
41 * <p>
42 * <strong>Warning:</strong>
43 * Serialized objects of this class will not be compatible with
44 * future Swing releases. The current serialization support is
45 * appropriate for short term storage or RMI between applications running
46 * the same version of Swing.  As of 1.4, support for long term storage
47 * of all JavaBeans&trade;
48 * has been added to the <code>java.beans</code> package.
49 * Please see {@link java.beans.XMLEncoder}.
50 *
51 * @param <E> the type of the elements of this model
52 *
53 * @author Hans Muller
54 * @since 1.2
55 */
56@SuppressWarnings("serial") // Same-version serialization only
57public class DefaultListModel<E> extends AbstractListModel<E>
58{
59    private Vector<E> delegate = new Vector<E>();
60
61    /**
62     * Returns the number of components in this list.
63     * <p>
64     * This method is identical to <code>size</code>, which implements the
65     * <code>List</code> interface defined in the 1.2 Collections framework.
66     * This method exists in conjunction with <code>setSize</code> so that
67     * <code>size</code> is identifiable as a JavaBean property.
68     *
69     * @return  the number of components in this list
70     * @see #size()
71     */
72    public int getSize() {
73        return delegate.size();
74    }
75
76    /**
77     * Returns the component at the specified index.
78     * <blockquote>
79     * <b>Note:</b> Although this method is not deprecated, the preferred
80     *    method to use is <code>get(int)</code>, which implements the
81     *    <code>List</code> interface defined in the 1.2 Collections framework.
82     * </blockquote>
83     * @param      index   an index into this list
84     * @return     the component at the specified index
85     * @exception  ArrayIndexOutOfBoundsException  if the <code>index</code>
86     *             is negative or greater than the current size of this
87     *             list
88     * @see #get(int)
89     */
90    public E getElementAt(int index) {
91        return delegate.elementAt(index);
92    }
93
94    /**
95     * Copies the components of this list into the specified array.
96     * The array must be big enough to hold all the objects in this list,
97     * else an <code>IndexOutOfBoundsException</code> is thrown.
98     *
99     * @param   anArray   the array into which the components get copied
100     * @see Vector#copyInto(Object[])
101     */
102    public void copyInto(Object anArray[]) {
103        delegate.copyInto(anArray);
104    }
105
106    /**
107     * Trims the capacity of this list to be the list's current size.
108     *
109     * @see Vector#trimToSize()
110     */
111    public void trimToSize() {
112        delegate.trimToSize();
113    }
114
115    /**
116     * Increases the capacity of this list, if necessary, to ensure
117     * that it can hold at least the number of components specified by
118     * the minimum capacity argument.
119     *
120     * @param   minCapacity   the desired minimum capacity
121     * @see Vector#ensureCapacity(int)
122     */
123    public void ensureCapacity(int minCapacity) {
124        delegate.ensureCapacity(minCapacity);
125    }
126
127    /**
128     * Sets the size of this list.
129     *
130     * @param   newSize   the new size of this list
131     * @see Vector#setSize(int)
132     */
133    public void setSize(int newSize) {
134        int oldSize = delegate.size();
135        delegate.setSize(newSize);
136        if (oldSize > newSize) {
137            fireIntervalRemoved(this, newSize, oldSize-1);
138        }
139        else if (oldSize < newSize) {
140            fireIntervalAdded(this, oldSize, newSize-1);
141        }
142    }
143
144    /**
145     * Returns the current capacity of this list.
146     *
147     * @return  the current capacity
148     * @see Vector#capacity()
149     */
150    public int capacity() {
151        return delegate.capacity();
152    }
153
154    /**
155     * Returns the number of components in this list.
156     *
157     * @return  the number of components in this list
158     * @see Vector#size()
159     */
160    public int size() {
161        return delegate.size();
162    }
163
164    /**
165     * Tests whether this list has any components.
166     *
167     * @return  <code>true</code> if and only if this list has
168     *          no components, that is, its size is zero;
169     *          <code>false</code> otherwise
170     * @see Vector#isEmpty()
171     */
172    public boolean isEmpty() {
173        return delegate.isEmpty();
174    }
175
176    /**
177     * Returns an enumeration of the components of this list.
178     *
179     * @return  an enumeration of the components of this list
180     * @see Vector#elements()
181     */
182    public Enumeration<E> elements() {
183        return delegate.elements();
184    }
185
186    /**
187     * Tests whether the specified object is a component in this list.
188     *
189     * @param   elem   an object
190     * @return  <code>true</code> if the specified object
191     *          is the same as a component in this list
192     * @see Vector#contains(Object)
193     */
194    public boolean contains(Object elem) {
195        return delegate.contains(elem);
196    }
197
198    /**
199     * Searches for the first occurrence of <code>elem</code>.
200     *
201     * @param   elem   an object
202     * @return  the index of the first occurrence of the argument in this
203     *          list; returns <code>-1</code> if the object is not found
204     * @see Vector#indexOf(Object)
205     */
206    public int indexOf(Object elem) {
207        return delegate.indexOf(elem);
208    }
209
210    /**
211     * Searches for the first occurrence of <code>elem</code>, beginning
212     * the search at <code>index</code>.
213     *
214     * @param   elem    an desired component
215     * @param   index   the index from which to begin searching
216     * @return  the index where the first occurrence of <code>elem</code>
217     *          is found after <code>index</code>; returns <code>-1</code>
218     *          if the <code>elem</code> is not found in the list
219     * @see Vector#indexOf(Object,int)
220     */
221     public int indexOf(Object elem, int index) {
222        return delegate.indexOf(elem, index);
223    }
224
225    /**
226     * Returns the index of the last occurrence of <code>elem</code>.
227     *
228     * @param   elem   the desired component
229     * @return  the index of the last occurrence of <code>elem</code>
230     *          in the list; returns <code>-1</code> if the object is not found
231     * @see Vector#lastIndexOf(Object)
232     */
233    public int lastIndexOf(Object elem) {
234        return delegate.lastIndexOf(elem);
235    }
236
237    /**
238     * Searches backwards for <code>elem</code>, starting from the
239     * specified index, and returns an index to it.
240     *
241     * @param  elem    the desired component
242     * @param  index   the index to start searching from
243     * @return the index of the last occurrence of the <code>elem</code>
244     *          in this list at position less than <code>index</code>;
245     *          returns <code>-1</code> if the object is not found
246     * @see Vector#lastIndexOf(Object,int)
247     */
248    public int lastIndexOf(Object elem, int index) {
249        return delegate.lastIndexOf(elem, index);
250    }
251
252    /**
253     * Returns the component at the specified index.
254     * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index
255     * is negative or not less than the size of the list.
256     * <blockquote>
257     * <b>Note:</b> Although this method is not deprecated, the preferred
258     *    method to use is <code>get(int)</code>, which implements the
259     *    <code>List</code> interface defined in the 1.2 Collections framework.
260     * </blockquote>
261     *
262     * @param      index   an index into this list
263     * @return     the component at the specified index
264     * @see #get(int)
265     * @see Vector#elementAt(int)
266     */
267    public E elementAt(int index) {
268        return delegate.elementAt(index);
269    }
270
271    /**
272     * Returns the first component of this list.
273     * Throws a <code>NoSuchElementException</code> if this
274     * vector has no components.
275     * @return     the first component of this list
276     * @see Vector#firstElement()
277     */
278    public E firstElement() {
279        return delegate.firstElement();
280    }
281
282    /**
283     * Returns the last component of the list.
284     * Throws a <code>NoSuchElementException</code> if this vector
285     * has no components.
286     *
287     * @return  the last component of the list
288     * @see Vector#lastElement()
289     */
290    public E lastElement() {
291        return delegate.lastElement();
292    }
293
294    /**
295     * Sets the component at the specified <code>index</code> of this
296     * list to be the specified element. The previous component at that
297     * position is discarded.
298     * <p>
299     * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index
300     * is invalid.
301     * <blockquote>
302     * <b>Note:</b> Although this method is not deprecated, the preferred
303     *    method to use is <code>set(int,Object)</code>, which implements the
304     *    <code>List</code> interface defined in the 1.2 Collections framework.
305     * </blockquote>
306     *
307     * @param      element what the component is to be set to
308     * @param      index   the specified index
309     * @see #set(int,Object)
310     * @see Vector#setElementAt(Object,int)
311     */
312    public void setElementAt(E element, int index) {
313        delegate.setElementAt(element, index);
314        fireContentsChanged(this, index, index);
315    }
316
317    /**
318     * Deletes the component at the specified index.
319     * <p>
320     * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index
321     * is invalid.
322     * <blockquote>
323     * <b>Note:</b> Although this method is not deprecated, the preferred
324     *    method to use is <code>remove(int)</code>, which implements the
325     *    <code>List</code> interface defined in the 1.2 Collections framework.
326     * </blockquote>
327     *
328     * @param      index   the index of the object to remove
329     * @see #remove(int)
330     * @see Vector#removeElementAt(int)
331     */
332    public void removeElementAt(int index) {
333        delegate.removeElementAt(index);
334        fireIntervalRemoved(this, index, index);
335    }
336
337    /**
338     * Inserts the specified element as a component in this list at the
339     * specified <code>index</code>.
340     * <p>
341     * Throws an <code>ArrayIndexOutOfBoundsException</code> if the index
342     * is invalid.
343     * <blockquote>
344     * <b>Note:</b> Although this method is not deprecated, the preferred
345     *    method to use is <code>add(int,Object)</code>, which implements the
346     *    <code>List</code> interface defined in the 1.2 Collections framework.
347     * </blockquote>
348     *
349     * @param      element the component to insert
350     * @param      index   where to insert the new component
351     * @exception  ArrayIndexOutOfBoundsException  if the index was invalid
352     * @see #add(int,Object)
353     * @see Vector#insertElementAt(Object,int)
354     */
355    public void insertElementAt(E element, int index) {
356        delegate.insertElementAt(element, index);
357        fireIntervalAdded(this, index, index);
358    }
359
360    /**
361     * Adds the specified component to the end of this list.
362     *
363     * @param   element   the component to be added
364     * @see Vector#addElement(Object)
365     */
366    public void addElement(E element) {
367        int index = delegate.size();
368        delegate.addElement(element);
369        fireIntervalAdded(this, index, index);
370    }
371
372    /**
373     * Removes the first (lowest-indexed) occurrence of the argument
374     * from this list.
375     *
376     * @param   obj   the component to be removed
377     * @return  <code>true</code> if the argument was a component of this
378     *          list; <code>false</code> otherwise
379     * @see Vector#removeElement(Object)
380     */
381    public boolean removeElement(Object obj) {
382        int index = indexOf(obj);
383        boolean rv = delegate.removeElement(obj);
384        if (index >= 0) {
385            fireIntervalRemoved(this, index, index);
386        }
387        return rv;
388    }
389
390
391    /**
392     * Removes all components from this list and sets its size to zero.
393     * <blockquote>
394     * <b>Note:</b> Although this method is not deprecated, the preferred
395     *    method to use is <code>clear</code>, which implements the
396     *    <code>List</code> interface defined in the 1.2 Collections framework.
397     * </blockquote>
398     *
399     * @see #clear()
400     * @see Vector#removeAllElements()
401     */
402    public void removeAllElements() {
403        int index1 = delegate.size()-1;
404        delegate.removeAllElements();
405        if (index1 >= 0) {
406            fireIntervalRemoved(this, 0, index1);
407        }
408    }
409
410
411    /**
412     * Returns a string that displays and identifies this
413     * object's properties.
414     *
415     * @return a String representation of this object
416     */
417   public String toString() {
418        return delegate.toString();
419    }
420
421
422    /* The remaining methods are included for compatibility with the
423     * Java 2 platform Vector class.
424     */
425
426    /**
427     * Returns an array containing all of the elements in this list in the
428     * correct order.
429     *
430     * @return an array containing the elements of the list
431     * @see Vector#toArray()
432     */
433    public Object[] toArray() {
434        Object[] rv = new Object[delegate.size()];
435        delegate.copyInto(rv);
436        return rv;
437    }
438
439    /**
440     * Returns the element at the specified position in this list.
441     * <p>
442     * Throws an <code>ArrayIndexOutOfBoundsException</code>
443     * if the index is out of range
444     * (<code>index &lt; 0 || index &gt;= size()</code>).
445     *
446     * @param index index of element to return
447     * @return the element at the specified position in this list
448     */
449    public E get(int index) {
450        return delegate.elementAt(index);
451    }
452
453    /**
454     * Replaces the element at the specified position in this list with the
455     * specified element.
456     * <p>
457     * Throws an <code>ArrayIndexOutOfBoundsException</code>
458     * if the index is out of range
459     * (<code>index &lt; 0 || index &gt;= size()</code>).
460     *
461     * @param index index of element to replace
462     * @param element element to be stored at the specified position
463     * @return the element previously at the specified position
464     */
465    public E set(int index, E element) {
466        E rv = delegate.elementAt(index);
467        delegate.setElementAt(element, index);
468        fireContentsChanged(this, index, index);
469        return rv;
470    }
471
472    /**
473     * Inserts the specified element at the specified position in this list.
474     * <p>
475     * Throws an <code>ArrayIndexOutOfBoundsException</code> if the
476     * index is out of range
477     * (<code>index &lt; 0 || index &gt; size()</code>).
478     *
479     * @param index index at which the specified element is to be inserted
480     * @param element element to be inserted
481     */
482    public void add(int index, E element) {
483        delegate.insertElementAt(element, index);
484        fireIntervalAdded(this, index, index);
485    }
486
487    /**
488     * Removes the element at the specified position in this list.
489     * Returns the element that was removed from the list.
490     * <p>
491     * Throws an <code>ArrayIndexOutOfBoundsException</code>
492     * if the index is out of range
493     * (<code>index &lt; 0 || index &gt;= size()</code>).
494     *
495     * @param index the index of the element to removed
496     * @return the element previously at the specified position
497     */
498    public E remove(int index) {
499        E rv = delegate.elementAt(index);
500        delegate.removeElementAt(index);
501        fireIntervalRemoved(this, index, index);
502        return rv;
503    }
504
505    /**
506     * Removes all of the elements from this list.  The list will
507     * be empty after this call returns (unless it throws an exception).
508     */
509    public void clear() {
510        int index1 = delegate.size()-1;
511        delegate.removeAllElements();
512        if (index1 >= 0) {
513            fireIntervalRemoved(this, 0, index1);
514        }
515    }
516
517    /**
518     * Deletes the components at the specified range of indexes.
519     * The removal is inclusive, so specifying a range of (1,5)
520     * removes the component at index 1 and the component at index 5,
521     * as well as all components in between.
522     * <p>
523     * Throws an <code>ArrayIndexOutOfBoundsException</code>
524     * if the index was invalid.
525     * Throws an <code>IllegalArgumentException</code> if
526     * <code>fromIndex &gt; toIndex</code>.
527     *
528     * @param      fromIndex the index of the lower end of the range
529     * @param      toIndex   the index of the upper end of the range
530     * @see        #remove(int)
531     */
532    public void removeRange(int fromIndex, int toIndex) {
533        if (fromIndex > toIndex) {
534            throw new IllegalArgumentException("fromIndex must be <= toIndex");
535        }
536        for(int i = toIndex; i >= fromIndex; i--) {
537            delegate.removeElementAt(i);
538        }
539        fireIntervalRemoved(this, fromIndex, toIndex);
540    }
541
542    /*
543    public void addAll(Collection c) {
544    }
545
546    public void addAll(int index, Collection c) {
547    }
548    */
549}
550