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