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