xref: /AOO42X/main/javaunohelper/com/sun/star/lib/uno/helper/InterfaceContainer.java (revision b0efeae40e43e6d4ccd561d22ec612d42773857b)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 package com.sun.star.lib.uno.helper;
25 import java.util.Iterator;
26 import java.util.ListIterator;
27 import java.util.NoSuchElementException;
28 import java.util.Collection;
29 import com.sun.star.lang.EventObject;
30 import com.sun.star.lang.XEventListener;
31 import com.sun.star.uno.UnoRuntime;
32 
33 /**
34  * This class is a container for interfaces.
35  *
36  * It is intended to be used as storage for UNO interface of a specific type.
37  * The client has to ensure that the container contains only elements of the same
38  * type. If one needs to store different types, then one uses OMultiTypeInterfaceContainer.
39  * When the client calls disposeAndClear, the contained objects are queried for
40  * com.sun.star.lang.XEventListener and disposing is called. Afterwards
41  * the list cannot be used anymore.
42  *
43  * This list does not allow null values.
44  * All methods are thread-safe. The same holds true for
45  * iterators, issued by this class. Several iterators can exist at the same time and can also
46  * be modified (java.util.ListIterator.add, java.util.ListIterator.remove etc.). To make this work,
47  * the InterfaceContainer provides the iterators with copys of the list's data.
48  * The add and remove calls on the iterator modify the data in the iterator's list as well as
49  * in InterfaceContainer. Modification on InterfaceContainer, however, are not
50  * synchronized with existing iterators. For example
51  * <pre>
52  * InterfaceContainer cont= new InterfaceContainer();
53  * ListIterator it= cont.listIterator();
54  *
55  * cont.add( someInterface);
56  * // one cannot obtain someInterface through iterator it,
57  * // instead get a new iterator
58  * it= cont.listIterator();
59  * // it now keeps a fresh copy of cont and hence contains someInterface
60  *
61  * // Adding an interface on the iterator will cause the interface also to be added
62  * // to InterfaceContainer
63  * it.add( someOtherInterface);
64  * // someOtherInterface is now in it and cont
65  * ListIterator it2= cont.listIterator();
66  * //someOtherInterface can also be obtained by all newly created iterators, e.g. it2.
67  * </pre>
68  *
69  *  The add and remove methods of an iterator work on a particular location within a list,
70  *  dependent on what the value of the iterator's cursor is. After the call the value at the
71  *  appropriate position has been modified. Since the iterator received a copy of InterfaceContainer's
72  *  data, InterfaceContainer may have been modified (by List methods or through other iterators).
73  *  Therefore both data sets may not contain the same elements anymore. Consequently, a List method
74  *  that modifies data, does not modify InterfaceContainer's data at a certain index
75  *  (according to the iterators cursor). Instead, new elements are added at the end of list. When
76  *  Iterator.remove is called, then the first occurrence of that element in InterfaceContainer
77  *  is removed.
78  *  ListIterator.set is not supported.
79  *
80  * A lot of  methods resemble those of the  to java.util.List interface, although
81  * this class does not implement it. However, the list iterators returned, for example by
82  * the listIterator method implement the java.util.ListIterator interface.
83  * Implementing the List interface would mean to support all none - optional methods as
84  * prescribed by the interface declaration. Among those is the subList method which returns
85  * a range of values of the list's data wrapped in a List implementation. Changes to the sub
86  * list have to cause changes in the main list. This is a problem, since this class is to be
87  * used in a multi-threaded environment. The sub list could work on a copy as the iterators
88  * do, but all the functions which work on an given index could not be properly supported.
89  * Unfortunately, the List interface documentation states that all optional methods implemented
90  * by the list have to be implemented in the sub list. That would mean to do without all those
91  * critical methods, although they might work well in the "main list" (as opposed to sub list).
92  */
93 public class InterfaceContainer implements Cloneable
94 {
95     final boolean DEBUG= false;
96     /**
97      * The array buffer into which the elements of the ArrayList are stored.
98      * The capacity of the ArrayList is the length of this array buffer.
99      */
100     Object elementData[];
101 
102     /**
103      * The size of the ArrayList (the number of elements it contains).
104      */
105     private int size;
106 
107 
108     //private ArrayList data= new ArrayList();
109     /** Creates a new instance of InterfaceContainer */
110     public InterfaceContainer()
111     {
112         this(10);
113     }
114     /**
115      * Constructs an empty list with the specified initial capacity.
116      *
117      * @param   initialCapacity   the initial capacity of the list.
118      * @exception IllegalArgumentException if the specified initial capacity
119      *            is negative
120      */
121     public InterfaceContainer(int initialCapacity)
122     {
123         if (initialCapacity < 0)
124             throw new java.lang.IllegalArgumentException("Illegal Capacity: "+
125             initialCapacity);
126         this.elementData = new Object[initialCapacity];
127     }
128 
129     /**
130      * Trims the capacity of this <tt>ArrayList</tt> instance to be the
131      * list's current size.  An application can use this operation to minimize
132      * the storage of an <tt>ArrayList</tt> instance.
133      */
134     synchronized public void trimToSize()
135     {
136         int oldCapacity = elementData.length;
137         if (size < oldCapacity)
138         {
139             Object oldData[] = elementData;
140             elementData = new Object[size];
141             System.arraycopy(oldData, 0, elementData, 0, size);
142         }
143     }
144 
145     /**
146      * Increases the capacity of this <tt>ArrayList</tt> instance, if
147      * necessary, to ensure  that it can hold at least the number of elements
148      * specified by the minimum capacity argument.
149      *
150      * @param   minCapacity   the desired minimum capacity.
151      */
152     synchronized public void ensureCapacity(int minCapacity)
153     {
154         int oldCapacity = elementData.length;
155         if (minCapacity > oldCapacity)
156         {
157             Object oldData[] = elementData;
158             int newCapacity = (oldCapacity * 3)/2 + 1;
159             if (newCapacity < minCapacity)
160                 newCapacity = minCapacity;
161             elementData = new Object[newCapacity];
162             System.arraycopy(oldData, 0, elementData, 0, size);
163         }
164     }
165 
166     /**
167      * Appends the specified element to the end of this list.
168      *
169      * @param o element to be appended to this list.
170      * @return <tt>true</tt> (as per the general contract of Collection.add).
171      */
172     synchronized public boolean add(Object o)
173     {
174         boolean ret= false;
175         if (elementData != null && o != null)
176         {
177             ensureCapacity(size + 1);  // Increments modCount!!
178             elementData[size++] = o;
179             ret= true;
180         }
181         return ret;
182     }
183 
184     /**
185      * Inserts the specified element at the specified position in this
186      * list. Shifts the element currently at that position (if any) and
187      * any subsequent elements to the right (adds one to their indices).
188      *
189      * @param index index at which the specified element is to be inserted.
190      * @param element element to be inserted.
191      * @throws    IndexOutOfBoundsException if index is out of range
192      *        <tt>(index &lt; 0 || index &gt; size())</tt>.
193      */
194     synchronized public void add(int index, Object element)
195     {
196         if (elementData != null && element != null)
197         {
198             if (index > size || index < 0)
199                 throw new IndexOutOfBoundsException(
200                 "Index: "+index+", Size: "+size);
201 
202             ensureCapacity(size+1);
203             System.arraycopy(elementData, index, elementData, index + 1,
204             size - index);
205             elementData[index] = element;
206             size++;
207         }
208     }
209 
210 
211     /**
212      * Appends all of the elements in the specified Collection to the end of
213      * this list, in the order that they are returned by the
214      * specified Collection's Iterator.  The behavior of this operation is
215      * undefined if the specified Collection is modified while the operation
216      * is in progress.  (This implies that the behavior of this call is
217      * undefined if the specified Collection is this list, and this
218      * list is nonempty.)
219      *
220      * @param c the elements to be inserted into this list.
221      * @throws    IndexOutOfBoundsException if index out of range <tt>(index
222      *        &lt; 0 || index &gt; size())</tt>.
223      */
224     synchronized public boolean addAll(Collection c)
225     {
226         int numNew = c.size();
227         ensureCapacity(size + numNew);
228 
229         Iterator e = c.iterator();
230         for (int i=0; i<numNew; i++)
231         {
232             Object o= e.next();
233             if (o != null)
234                 elementData[size++] = o;
235         }
236         return numNew != 0;
237     }
238     /**
239      * Inserts all of the elements in the specified Collection into this
240      * list, starting at the specified position.  Shifts the element
241      * currently at that position (if any) and any subsequent elements to
242      * the right (increases their indices).  The new elements will appear
243      * in the list in the order that they are returned by the
244      * specified Collection's iterator.
245      *
246      * @param index index at which to insert first element
247      *          from the specified collection.
248      * @param c elements to be inserted into this list.
249      * @throws    IndexOutOfBoundsException if index out of range <tt>(index
250      *        &lt; 0 || index &gt; size())</tt>.
251      */
252     synchronized public boolean addAll(int index, Collection c)
253     {
254         boolean ret= false;
255         if (elementData != null)
256         {
257             if (index > size || index < 0)
258                 throw new IndexOutOfBoundsException(
259                 "Index: "+index+", Size: "+size);
260             // only add  the non-null elements
261             int sizeCol= c.size();
262             Object[] arColl= new Object[sizeCol];
263             Iterator icol= c.iterator();
264             int curIndex= 0;
265             for (int i=0; i < sizeCol; i++)
266             {
267                 Object o= icol.next();
268                 if (o != null)
269                     arColl[curIndex++]= o;
270             }
271             int numNew = curIndex;
272             ensureCapacity(size + numNew);  // Increments modCount!!
273 
274             int numMoved = size - index;
275             if (numMoved > 0)
276                 System.arraycopy(elementData, index, elementData, index + numNew,
277                 numMoved);
278 
279             for (int i=0; i<numNew; i++)
280             {
281                 elementData[index++]= arColl[i];
282             }
283             size += numNew;
284             ret= numNew != 0;
285         }
286         return ret;
287     }
288 
289     /**
290      * Removes all of the elements from this list.  The list will
291      * be empty after this call returns.
292      */
293     synchronized public void clear()
294     {
295         if (elementData != null)
296         {
297             // Let gc do its work
298             for (int i = 0; i < size; i++)
299                 elementData[i] = null;
300 
301             size = 0;
302         }
303     }
304     /**
305      * Returns <tt>true</tt> if this list contains the specified element.
306      *
307      * @param elem element whose presence in this List is to be tested.
308      */
309     synchronized public boolean contains(Object elem)
310     {
311         return indexOf(elem) >= 0;
312     }
313 
314     synchronized public boolean containsAll(Collection collection)
315     {
316         boolean retVal= true;
317         if (elementData != null && collection != null)
318         {
319             Iterator it= collection.iterator();
320             while (it.hasNext())
321             {
322                 Object obj= it.next();
323                 if (false == contains(obj))
324                 {
325                     retVal= false;
326                     break;
327                 }
328             }
329         }
330         return retVal;
331     }
332     /**
333      * Returns the element at the specified position in this list.
334      *
335      * @param  index index of element to return.
336      * @return the element at the specified position in this list.
337      * @throws    IndexOutOfBoundsException if index is out of range <tt>(index
338      *        &lt; 0 || index &gt;= size())</tt>.
339      */
340     synchronized public Object get(int index)
341     {
342         if (elementData != null)
343         {
344             RangeCheck(index);
345             return elementData[index];
346         }
347         return null;
348     }
349 
350     /**
351      * Searches for the first occurrence of the given argument, testing
352      * for equality using the <tt>equals</tt> method.
353      *
354      * @param   elem   an object.
355      * @return  the index of the first occurrence of the argument in this
356      *          list; returns <tt>-1</tt> if the object is not found.
357      * @see     Object#equals(Object)
358      */
359     synchronized public int indexOf(Object elem)
360     {
361         int index= -1;
362         if (elementData != null && elem != null)
363         {
364             for (int i = 0; i < size; i++)
365             {
366                 if (elem == elementData[i])
367                 {
368                     index= i;
369                     break;
370                 }
371             }
372 
373             if (index == -1)
374             {
375                 for (int i = 0; i < size; i++)
376                 {
377                     if (UnoRuntime.areSame(elem, elementData[i]))
378                     {
379                         index= i;
380                         break;
381                     }
382                 }
383             }
384         }
385         return index;
386     }
387     /**
388      * Tests if this list has no elements.
389      *
390      * @return  <tt>true</tt> if this list has no elements;
391      *          <tt>false</tt> otherwise.
392      */
393     synchronized public boolean isEmpty()
394     {
395         return size == 0;
396     }
397 
398     synchronized public Iterator iterator()
399     {
400         if (elementData != null)
401         {
402             InterfaceContainer aCopy= (InterfaceContainer) clone();
403             return new Itr(aCopy);
404         }
405         return null;
406     }
407     /**
408      * Returns the index of the last occurrence of the specified object in
409      * this list.
410      *
411      * @param   elem   the desired element.
412      * @return  the index of the last occurrence of the specified object in
413      *          this list; returns -1 if the object is not found.
414      */
415     synchronized public int lastIndexOf(Object elem)
416     {
417         int index= -1;
418         if (elementData != null && elem != null)
419         {
420             for (int i = size-1; i >= 0; i--)
421             {
422                 if (elem == elementData[i])
423                 {
424                     index= i;
425                     break;
426                 }
427             }
428             if (index == -1)
429             {
430                 for (int i = size-1; i >= 0; i--)
431                 {
432                     if (UnoRuntime.areSame(elem, elementData[i]))
433                     {
434                         index= i;
435                         break;
436                     }
437                 }
438             }
439         }
440         return index;
441     }
442 
443     /**
444 <<<<<<< HEAD
445      * Returns a shallow copy of this <tt>ArrayList</tt> instance. The contained
446 =======
447      * Returns a shallow copy of this <code>ArrayList</code> instance. The contained
448 >>>>>>> 3309286857 (pre-commit auto remove trailing whitespace from java files (#382))
449      * references are copied but the objects not.
450      *
451      * @return  a clone of this <tt>List</tt> instance.
452      */
453     synchronized public Object clone()
454     {
455         Object ret= null;
456         if (elementData != null)
457         {
458             InterfaceContainer cont= new InterfaceContainer();
459             cont.elementData = new Object[size];
460             cont.size= size;
461             System.arraycopy(elementData, 0, cont.elementData, 0, size);
462             ret= cont;
463         }
464         return ret;
465     }
466     synchronized public ListIterator listIterator()
467     {
468         return listIterator(0);
469     }
470 
471     /** The iterator keeps a copy of the list. Changes to InterfaceContainer do not
472      *  affect the data of the iterator. Conversely, changes to the iterator are effect
473      *  InterfaceContainer.
474      *
475      * @param index
476      */
477     synchronized public ListIterator listIterator(int index)
478     {
479         if (elementData != null)
480         {
481             InterfaceContainer aCopy= (InterfaceContainer) clone();
482             return new LstItr(aCopy, index);
483         }
484         return null;
485     }
486     /**
487      * Removes the element at the specified position in this list.
488      * Shifts any subsequent elements to the left (subtracts one from their
489      * indices).
490      *
491      * @param index the index of the element to removed.
492      * @return the element that was removed from the list.
493      * @throws    IndexOutOfBoundsException if index out of range <tt>(index
494      *        &lt; 0 || index &gt;= size())</tt>.
495      */
496     synchronized public Object remove(int index)
497     {
498         Object ret= null;
499         if (elementData != null)
500         {
501             RangeCheck(index);
502             ret= elementData[index];
503 
504             int numMoved = size - index - 1;
505             if (numMoved > 0)
506                 System.arraycopy(elementData, index+1, elementData, index,
507                 numMoved);
508             elementData[--size] = null; // Let gc do its work
509         }
510         return ret;
511     }
512 
513 
514     /** Parameter obj may  */
515     synchronized public boolean remove(Object obj)
516     {
517         boolean ret= false;
518         if (elementData != null && obj != null)
519         {
520             int index= indexOf(obj);
521             if (index != -1)
522             {
523                 ret= true;
524                 remove(index);
525             }
526         }
527         return ret;
528     }
529 
530     synchronized public boolean removeAll(Collection collection)
531     {
532         boolean retVal= false;
533         if (elementData != null && collection != null)
534         {
535             Iterator it= collection.iterator();
536             while (it.hasNext())
537             {
538                 Object obj= it.next();
539                 boolean bMod= remove( obj);
540                 if (bMod)
541                     retVal= true;
542             }
543         }
544         return retVal;
545     }
546 
547     synchronized public boolean retainAll(Collection collection)
548     {
549         boolean retVal= false;
550         if (elementData != null && collection != null)
551         {
552             // iterate over data
553             Object[] arRetained= new Object[size];
554             int indexRetained= 0;
555             for(int i= 0; i < size; i++)
556             {
557                 Object curElem= elementData[i];
558                 // try to find the element in collection
559                 Iterator itColl= collection.iterator();
560                 boolean bExists= false;
561                 while (itColl.hasNext())
562                 {
563                     if (curElem == itColl.next())
564                     {
565                         // current element is in collection
566                         bExists= true;
567                         break;
568                     }
569                 }
570                 if (bExists == false)
571                 {
572                     itColl= collection.iterator();
573                     while (itColl.hasNext())
574                     {
575                         Object o= itColl.next();
576                         if (o != null)
577                         {
578                             if (UnoRuntime.areSame(o, curElem))
579                             {
580                                 bExists= true;
581                                 break;
582                             }
583                         }
584                     }
585                 }
586                 if (bExists == true)
587                     arRetained[indexRetained++]= curElem;
588             }
589             retVal= size != indexRetained;
590             if (indexRetained > 0)
591             {
592                 elementData= arRetained;
593                 size= indexRetained;
594             }
595         }
596         return retVal;
597     }
598 
599 
600     /** Not supported.
601      * @param index index of element to replace.
602      * @param element element to be stored at the specified position.
603      * @return the element previously at the specified position.
604      * @throws    IndexOutOfBoundsException if index out of range
605      *        <tt>(index &lt; 0 || index &gt;= size())</tt>.
606      */
607     synchronized public Object set(int index, Object element)
608     {
609           Object ret= null;
610           if (elementData != null && element != null)
611           {
612               RangeCheck(index);
613               ret = elementData[index];
614               elementData[index] = element;
615           }
616           return ret;
617     }
618 
619     /**
620      * Returns the number of elements in this list.
621      *
622      * @return  the number of elements in this list.
623      */
624     synchronized public int size()
625     {
626         if (elementData != null)
627             return size;
628         return 0;
629     }
630 
631 
632     /**
633      * Returns an array containing all of the elements in this list
634      * in the correct order.
635      *
636      * @return an array containing all of the elements in this list
637      *         in the correct order.
638      */
639     synchronized public Object[] toArray()
640     {
641         if (elementData != null)
642         {
643             Object[] result = new Object[size];
644             System.arraycopy(elementData, 0, result, 0, size);
645             return result;
646         }
647         return null;
648     }
649 
650     /**
651      * Returns an array containing all of the elements in this list in the
652      * correct order.  The runtime type of the returned array is that of the
653      * specified array.  If the list fits in the specified array, it is
654      * returned therein.  Otherwise, a new array is allocated with the runtime
655      * type of the specified array and the size of this list.<p>
656      *
657      * If the list fits in the specified array with room to spare (i.e., the
658      * array has more elements than the list), the element in the array
659      * immediately following the end of the collection is set to
660      * <tt>null</tt>.  This is useful in determining the length of the list
661      * <i>only</i> if the caller knows that the list does not contain any
662      * <tt>null</tt> elements.
663      *
664      * @param a the array into which the elements of the list are to
665      *      be stored, if it is big enough; otherwise, a new array of the
666      *      same runtime type is allocated for this purpose.
667      * @return an array containing the elements of the list.
668      * @throws ArrayStoreException if the runtime type of a is not a supertype
669      *         of the runtime type of every element in this list.
670      */
671     synchronized public Object[] toArray(Object a[])
672     {
673         if (a.length < size)
674             a = (Object[])java.lang.reflect.Array.newInstance(
675             a.getClass().getComponentType(), size);
676         if (elementData != null)
677             System.arraycopy(elementData, 0, a, 0, size);
678 
679         if (a.length > size)
680             a[size] = null;
681 
682         return a;
683     }
684 
685     /**
686      * Check if the given index is in range.  If not, throw an appropriate
687      * runtime exception.
688      */
689     private void RangeCheck(int index)
690     {
691         if (index >= size || index < 0)
692             throw new IndexOutOfBoundsException(
693             "Index: "+index+", Size: "+size);
694     }
695 
696     public void disposeAndClear(EventObject evt)
697     {
698         Iterator aIt;
699         synchronized (this)
700         {
701             aIt= iterator();
702             // Container freigeben, falls im disposing neue Eintraege kommen
703             // set the member to null, the iterator delete the values
704             clear();
705             elementData= null;
706             size= 0;
707         }
708         if (aIt != null)
709         {
710             while( aIt.hasNext() )
711             {
712                 try
713                 {
714                     Object o= aIt.next();
715                     XEventListener evtListener= UnoRuntime.queryInterface(
716                     XEventListener.class, o);
717                     if( evtListener != null )
718                         evtListener.disposing( evt );
719                 }
720                 catch ( RuntimeException e)
721                 {
722                     // be robust, if e.g. a remote bridge has disposed already.
723                     // there is no way, to delegate the error to the caller :o(.
724                 }
725             }
726         }
727     }
728 
729 
730     private class Itr implements Iterator
731     {
732         InterfaceContainer dataIt;
733         /**
734          * Index of element to be returned by subsequent call to next.
735          */
736         int cursor= 0;
737         /**
738          * Index of element returned by most recent call to next or
739          * previous.  Reset to -1 if this element is deleted by a call
740          * to remove.
741          */
742         int lastRet = -1;
743 
744         /** The object that has been returned by most recent call to next
745          *  or previous. Reset to null if this element is deleted by a call
746          *  to remove.
747          */
748         Object lastRetObj= null;
749 
750         Itr(InterfaceContainer _data)
751         {
752             dataIt= _data;
753         }
754 
755         synchronized public boolean hasNext()
756         {
757             return cursor !=dataIt.size();
758         }
759 
760         public synchronized Object next()
761         {
762             try
763             {
764                 Object next = dataIt.get(cursor);
765                 lastRet = cursor++;
766                 lastRetObj= next;
767                 return next;
768             }
769             catch(java.lang.IndexOutOfBoundsException e)
770             {
771                 throw new java.util.NoSuchElementException();
772             }
773         }
774 
775         /** Removes the interface from the list, that has been last returned by a
776          *  call to next(). This is done according to the specification of the interface
777          *  method. The element is also removed from InterfaceContainer but independent
778          *  of the location. If the element is multiple times in InterfaceContainer then
779          *  it is up to the java.util.ArrayList implementation what element is removed.
780          */
781         public synchronized void remove()
782         {
783             if (lastRet == -1)
784                 throw new IllegalStateException();
785             // Remove the entry from InterfaceContainer.
786             InterfaceContainer.this.remove(lastRetObj);
787             dataIt.remove(lastRet);
788 
789             if (lastRet < cursor)
790                 cursor--;
791             lastRet = -1;
792             lastRetObj= null;
793         }
794     }
795 
796     private class LstItr extends Itr implements ListIterator
797     {
798 
799         LstItr(InterfaceContainer _data, int _index)
800         {
801             super(_data);
802             cursor= _index;
803         }
804 
805         /** Inserts an element to the iterators list according to the specification
806          *  of this interface method. The element is also added to InterfaceContainer
807          *  but its location within the list cannot be guaranteed.
808          */
809         public synchronized void add(Object o)
810         {
811             InterfaceContainer.this.add(o);
812             dataIt.add(cursor++, o);
813             lastRet = -1;
814             lastRetObj= null;
815         }
816 
817         synchronized public boolean hasPrevious()
818         {
819             return cursor != 0;
820         }
821 
822         synchronized public int nextIndex()
823         {
824             return cursor;
825         }
826 
827         public synchronized Object previous()
828         {
829             try
830             {
831                 Object previous = dataIt.get(--cursor);
832                 lastRet = cursor;
833                 lastRetObj= previous;
834                 return previous;
835             } catch(IndexOutOfBoundsException e)
836             {
837                 throw new NoSuchElementException();
838             }
839         }
840 
841         synchronized public int previousIndex()
842         {
843             return cursor-1;
844         }
845 
846         /** This is not possible since several iterators can modify InterfaceContainer
847          */
848         public synchronized void set(Object o)
849         {
850             throw new UnsupportedOperationException();
851         }
852 
853 
854     } // class LstItr
855 }
856