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, allthough
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  * Unfortunatly, 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, allthough 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 occurence 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      * Returns a shallow copy of this <tt>ArrayList</tt> instance. The contained
445      * references are copied but the objects not.
446      *
447      * @return  a clone of this <tt>List</tt> instance.
448      */
449     synchronized public Object clone()
450     {
451         Object ret= null;
452         if (elementData != null)
453         {
454             InterfaceContainer cont= new InterfaceContainer();
455             cont.elementData = new Object[size];
456             cont.size= size;
457             System.arraycopy(elementData, 0, cont.elementData, 0, size);
458             ret= cont;
459         }
460         return ret;
461     }
462     synchronized public ListIterator listIterator()
463     {
464         return listIterator(0);
465     }
466 
467     /** The iterator keeps a copy of the list. Changes to InterfaceContainer do not
468      *  affect the data of the iterator. Conversly, changes to the iterator are effect
469      *  InterfaceContainer.
470      */
471     synchronized public ListIterator listIterator(int index)
472     {
473         if (elementData != null)
474         {
475             InterfaceContainer aCopy= (InterfaceContainer) clone();
476             return new LstItr(aCopy, index);
477         }
478         return null;
479     }
480     /**
481      * Removes the element at the specified position in this list.
482      * Shifts any subsequent elements to the left (subtracts one from their
483      * indices).
484      *
485      * @param index the index of the element to removed.
486      * @return the element that was removed from the list.
487      * @throws    IndexOutOfBoundsException if index out of range <tt>(index
488      * 		  &lt; 0 || index &gt;= size())</tt>.
489      */
490     synchronized public Object remove(int index)
491     {
492         Object ret= null;
493         if (elementData != null)
494         {
495             RangeCheck(index);
496             ret= elementData[index];
497 
498             int numMoved = size - index - 1;
499             if (numMoved > 0)
500                 System.arraycopy(elementData, index+1, elementData, index,
501                 numMoved);
502             elementData[--size] = null; // Let gc do its work
503         }
504         return ret;
505     }
506 
507 
508     /** Parameter obj may  */
509     synchronized public boolean remove(Object obj)
510     {
511         boolean ret= false;
512         if (elementData != null && obj != null)
513         {
514             int index= indexOf(obj);
515             if (index != -1)
516             {
517                 ret= true;
518                 remove(index);
519             }
520         }
521         return ret;
522     }
523 
524     synchronized public boolean removeAll(Collection collection)
525     {
526         boolean retVal= false;
527         if (elementData != null && collection != null)
528         {
529             Iterator it= collection.iterator();
530             while (it.hasNext())
531             {
532                 Object obj= it.next();
533                 boolean bMod= remove( obj);
534                 if (bMod)
535                     retVal= true;
536             }
537         }
538         return retVal;
539     }
540 
541     synchronized public boolean retainAll(Collection collection)
542     {
543         boolean retVal= false;
544         if (elementData != null && collection != null)
545         {
546             // iterate over data
547             Object[] arRetained= new Object[size];
548             int indexRetained= 0;
549             for(int i= 0; i < size; i++)
550             {
551                 Object curElem= elementData[i];
552                 // try to find the element in collection
553                 Iterator itColl= collection.iterator();
554                 boolean bExists= false;
555                 while (itColl.hasNext())
556                 {
557                     if (curElem == itColl.next())
558                     {
559                         // current element is in collection
560                         bExists= true;
561                         break;
562                     }
563                 }
564                 if (bExists == false)
565                 {
566                     itColl= collection.iterator();
567                     while (itColl.hasNext())
568                     {
569                         Object o= itColl.next();
570                         if (o != null)
571                         {
572                             if (UnoRuntime.areSame(o, curElem))
573                             {
574                                 bExists= true;
575                                 break;
576                             }
577                         }
578                     }
579                 }
580                 if (bExists == true)
581                     arRetained[indexRetained++]= curElem;
582             }
583             retVal= size != indexRetained;
584             if (indexRetained > 0)
585             {
586                 elementData= arRetained;
587                 size= indexRetained;
588             }
589         }
590         return retVal;
591     }
592 
593 
594     /** Not supported.
595      * @param index index of element to replace.
596      * @param element element to be stored at the specified position.
597      * @return the element previously at the specified position.
598      * @throws    IndexOutOfBoundsException if index out of range
599      *		  <tt>(index &lt; 0 || index &gt;= size())</tt>.
600      */
601     synchronized public Object set(int index, Object element)
602     {
603           Object ret= null;
604           if (elementData != null && element != null)
605           {
606               RangeCheck(index);
607               ret = elementData[index];
608               elementData[index] = element;
609           }
610           return ret;
611     }
612 
613     /**
614      * Returns the number of elements in this list.
615      *
616      * @return  the number of elements in this list.
617      */
618     synchronized public int size()
619     {
620         if (elementData != null)
621             return size;
622         return 0;
623     }
624 
625 
626     /**
627      * Returns an array containing all of the elements in this list
628      * in the correct order.
629      *
630      * @return an array containing all of the elements in this list
631      * 	       in the correct order.
632      */
633     synchronized public Object[] toArray()
634     {
635         if (elementData != null)
636         {
637             Object[] result = new Object[size];
638             System.arraycopy(elementData, 0, result, 0, size);
639             return result;
640         }
641         return null;
642     }
643 
644     /**
645      * Returns an array containing all of the elements in this list in the
646      * correct order.  The runtime type of the returned array is that of the
647      * specified array.  If the list fits in the specified array, it is
648      * returned therein.  Otherwise, a new array is allocated with the runtime
649      * type of the specified array and the size of this list.<p>
650      *
651      * If the list fits in the specified array with room to spare (i.e., the
652      * array has more elements than the list), the element in the array
653      * immediately following the end of the collection is set to
654      * <tt>null</tt>.  This is useful in determining the length of the list
655      * <i>only</i> if the caller knows that the list does not contain any
656      * <tt>null</tt> elements.
657      *
658      * @param a the array into which the elements of the list are to
659      *		be stored, if it is big enough; otherwise, a new array of the
660      * 		same runtime type is allocated for this purpose.
661      * @return an array containing the elements of the list.
662      * @throws ArrayStoreException if the runtime type of a is not a supertype
663      *         of the runtime type of every element in this list.
664      */
665     synchronized public Object[] toArray(Object a[])
666     {
667         if (a.length < size)
668             a = (Object[])java.lang.reflect.Array.newInstance(
669             a.getClass().getComponentType(), size);
670         if (elementData != null)
671             System.arraycopy(elementData, 0, a, 0, size);
672 
673         if (a.length > size)
674             a[size] = null;
675 
676         return a;
677     }
678 
679     /**
680      * Check if the given index is in range.  If not, throw an appropriate
681      * runtime exception.
682      */
683     private void RangeCheck(int index)
684     {
685         if (index >= size || index < 0)
686             throw new IndexOutOfBoundsException(
687             "Index: "+index+", Size: "+size);
688     }
689 
690     public void disposeAndClear(EventObject evt)
691     {
692         Iterator aIt;
693         synchronized (this)
694         {
695             aIt= iterator();
696             // Container freigeben, falls im disposing neue Eintraege kommen
697             // set the member to null, the iterator delete the values
698             clear();
699             elementData= null;
700             size= 0;
701         }
702         if (aIt != null)
703         {
704             while( aIt.hasNext() )
705             {
706                 try
707                 {
708                     Object o= aIt.next();
709                     XEventListener evtListener= UnoRuntime.queryInterface(
710                     XEventListener.class, o);
711                     if( evtListener != null )
712                         evtListener.disposing( evt );
713                 }
714                 catch ( RuntimeException e)
715                 {
716                     // be robust, if e.g. a remote bridge has disposed already.
717                     // there is no way, to delegate the error to the caller :o(.
718                 }
719             }
720         }
721     }
722 
723 
724     private class Itr implements Iterator
725     {
726         InterfaceContainer dataIt;
727         /**
728          * Index of element to be returned by subsequent call to next.
729          */
730         int cursor= 0;
731         /**
732          * Index of element returned by most recent call to next or
733          * previous.  Reset to -1 if this element is deleted by a call
734          * to remove.
735          */
736         int lastRet = -1;
737 
738         /** The object that has been returned by most recent call to next
739          *  or previous. Reset to null if this element is deleted by a call
740          *  to remove.
741          */
742         Object lastRetObj= null;
743 
744         Itr(InterfaceContainer _data)
745         {
746             dataIt= _data;
747         }
748 
749         synchronized public boolean hasNext()
750         {
751             return cursor !=dataIt.size();
752         }
753 
754         public synchronized Object next()
755         {
756             try
757             {
758                 Object next = dataIt.get(cursor);
759                 lastRet = cursor++;
760                 lastRetObj= next;
761                 return next;
762             }
763             catch(java.lang.IndexOutOfBoundsException e)
764             {
765                 throw new java.util.NoSuchElementException();
766             }
767         }
768 
769         /** Removes the interface from the list, that has been last returned by a
770          *  call to next(). This is done according to the specification of the interface
771          *  method. The element is also removed from InterfaceContainer but independent
772          *  of the location. If the element is multiple times in InterfaceContainer then
773          *  it is up to the java.util.ArrayList implementation what element is removed.
774          */
775         public synchronized void remove()
776         {
777             if (lastRet == -1)
778                 throw new IllegalStateException();
779             // Remove the entry from InterfaceContainer.
780             InterfaceContainer.this.remove(lastRetObj);
781             dataIt.remove(lastRet);
782 
783             if (lastRet < cursor)
784                 cursor--;
785             lastRet = -1;
786             lastRetObj= null;
787         }
788     }
789 
790     private class LstItr extends Itr implements ListIterator
791     {
792 
793         LstItr(InterfaceContainer _data, int _index)
794         {
795             super(_data);
796             cursor= _index;
797         }
798 
799         /** Inserts an element to the iterators list according to the specification
800          *  of this interface method. The element is also added to InterfaceContainer
801          *  but its location within the list cannot be guaranteed.
802          */
803         public synchronized void add(Object o)
804         {
805             InterfaceContainer.this.add(o);
806             dataIt.add(cursor++, o);
807             lastRet = -1;
808             lastRetObj= null;
809         }
810 
811         synchronized public boolean hasPrevious()
812         {
813             return cursor != 0;
814         }
815 
816         synchronized public int nextIndex()
817         {
818             return cursor;
819         }
820 
821         public synchronized Object previous()
822         {
823             try
824             {
825                 Object previous = dataIt.get(--cursor);
826                 lastRet = cursor;
827                 lastRetObj= previous;
828                 return previous;
829             } catch(IndexOutOfBoundsException e)
830             {
831                 throw new NoSuchElementException();
832             }
833         }
834 
835         synchronized public int previousIndex()
836         {
837             return cursor-1;
838         }
839 
840         /** This is not possible since several iterators can modify InterfaceContainer
841          */
842         public synchronized void set(Object o)
843         {
844             throw new UnsupportedOperationException();
845         }
846 
847 
848     } // class LstItr
849 }
850 
851