View Javadoc

1   /*
2   Wotonomy: OpenStep design patterns for pure Java applications.
3   Copyright (C) 2001 Michael Powers
4   
5   This library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9   
10  This library is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  Lesser General Public License for more details.
14  
15  You should have received a copy of the GNU Lesser General Public
16  License along with this library; if not, see http://www.gnu.org
17  */
18  
19  package net.wotonomy.control;
20  
21  import java.util.Collection;
22  import java.util.Iterator;
23  import java.util.List;
24  
25  import net.wotonomy.foundation.NSMutableArray;
26  import net.wotonomy.foundation.NSRange;
27  
28  /***
29  * A package class that extends NSMutableArray but makes use
30  * of the fact that wotonomy's implementation extends ArrayList
31  * to intercept insertions and deletion and register and 
32  * unregister objects for change notifications as appropriate.
33  * Since we can't be sure of ArrayList's implementation, we're
34  * forced to override each and every add and remove method,
35  * some of which probably call each other.  However, 
36  * EOObserverCenter will only register us once per object.
37  */
38  class ObservableArray extends NSMutableArray
39  {
40      EOObserving observer;
41      
42      ObservableArray( EOObserving anObserver )
43      {
44          observer = anObserver;
45      }
46      
47  	/***
48  	* Removes the last object from the array.
49  	*/
50      public void removeLastObject ()
51      {
52  		remove( count() - 1 );    
53      }
54  
55  	/***
56  	* Removes the object at the specified index.
57  	*/
58      public void removeObjectAtIndex (int index)
59      {
60      	remove( index );
61      }
62  
63  	/***
64  	* Adds all objects in the specified collection.
65  	*/
66      public void addObjectsFromArray (Collection aCollection)
67      {
68      	addAll( aCollection );
69      }
70  
71  	/***
72  	* Removes all objects from the array.
73  	*/
74      public void removeAllObjects ()
75      {
76      	clear();
77      }
78  
79  	/***
80  	* Removes all objects equivalent to the specified object
81  	* within the range of specified indices.
82  	*/
83      public void removeObject (Object anObject, NSRange aRange)
84      {
85      	if ( ( anObject == null ) || ( aRange == null ) ) return;
86  	    
87  	    int loc = aRange.location();
88  	    int max = aRange.maxRange();
89  	    for ( int i = loc; i < max; i++ )
90  	    {
91  	    	if ( anObject.equals( get( i ) ) )
92  		    {
93  		    	remove( i );
94  			    i = i - 1;
95  			    max = max - 1;
96  		    }
97  	    }
98      }
99  
100 	/***
101 	* Removes all instances of the specified object within the 
102 	* range of specified indices, comparing by reference.
103 	*/
104     public void removeIdenticalObject (Object anObject, NSRange aRange)
105     {
106     	if ( ( anObject == null ) || ( aRange == null ) ) return;
107 	    
108 	    int loc = aRange.location();
109 	    int max = aRange.maxRange();
110 	    for ( int i = loc; i < max; i++ )
111 	    {
112 	    	if ( anObject == get( i ) )
113 		    {
114 		    	remove( i );
115 			    i = i - 1;
116 			    max = max - 1;
117 		    }
118 	    }
119     }
120 
121 	/***
122 	* Removes all objects in the specified collection from the array.
123 	*/
124     public void removeObjectsInArray (Collection aCollection)
125     {
126     	removeAll( aCollection );
127     }
128 
129 	/***
130 	* Removes all objects in the indices within the specified range 
131 	* from the array.
132 	*/
133     public void removeObjectsInRange (NSRange aRange)
134     {
135     	if ( aRange == null ) return;
136 	    
137 	    for ( int i = 0; i < aRange.length(); i++ )
138 	    {
139 	    	remove( aRange.location() );
140 	    }
141     }
142 
143 	/***
144 	* Replaces objects in the current range with objects from
145 	* the specified range of the specified array.  If currentRange
146 	* is larger than otherRange, the extra objects are removed.
147 	* If otherRange is larger than currentRange, the extra objects
148 	* are added.
149 	*/
150     public void replaceObjectsInRange (NSRange currentRange, 
151     	List otherArray, NSRange otherRange)
152 	{
153 		if ( ( currentRange == null ) || ( otherArray == null ) ||
154 			( otherRange == null ) ) return;
155 	
156 		// transform otherRange if out of bounds for array
157 		if ( otherRange.maxRange() > otherArray.size() )
158 		{
159 			// TODO: Test this logic.
160 			int loc = Math.min( otherRange.location(), otherArray.size() - 1 );
161 			otherRange = new NSRange( loc, otherArray.size() - loc ); 
162 		}
163 		
164 		Object o;
165 		List subList = subList( 
166 			currentRange.location(), currentRange.maxRange() );
167 		int otherIndex = otherRange.location();
168 		// TODO: Test this logic.
169 		for ( int i = 0; i < subList.size(); i++ )
170 		{
171 			if ( otherIndex < otherRange.maxRange() )
172 			{ // set object
173 				subList.set( i, otherArray.get( otherIndex ) ); 
174 			}
175 			else
176 			{ // remove extra elements from currentRange
177 				subList.remove( i );
178 				i--; 
179 			}
180 			otherIndex++;
181 		}
182 		// TODO: Test this logic.
183 		for ( int i = otherIndex; i < otherRange.maxRange(); i++ )
184 		{
185 			add( otherArray.get( i ) );
186 		}
187 	}
188 
189 	/***
190 	* Clears the current array and then populates it with the
191 	* contents of the specified collection.
192 	*/
193     public void setArray (Collection aCollection)
194     {
195     	clear();
196 	    addAll( aCollection );
197     }
198 
199 	/***
200 	* Removes all objects equivalent to the specified object. 
201 	*/
202     public void removeObject (Object anObject)
203     {
204         remove( anObject );
205     }
206 
207 	/***
208 	* Removes all occurences of the specified object,
209 	* comparing by reference.
210 	*/
211     public void removeIdenticalObject (Object anObject)
212     {
213         EOObserverCenter.removeObserver( observer, anObject );
214         super.removeIdenticalObject( anObject );
215     }
216 
217 	/***
218 	* Inserts the specified object into this array at the
219 	* specified index.
220 	*/
221     public void insertObjectAtIndex (Object anObject, int anIndex)
222     {
223     	add( anIndex, anObject );
224     }
225     
226 	/***
227 	* Replaces the object at the specified index with the 
228 	* specified object.
229 	*/
230     public void replaceObjectAtIndex (int anIndex, Object anObject)
231     {
232     	set( anIndex, anObject );
233     }
234 
235 	/***
236 	* Adds the specified object to the end of this array.
237 	*/
238     public void addObject (Object anObject) 
239     {
240     	add( anObject );
241     }
242     
243     // interface List: mutators
244 
245 	public void add(int index, Object element) 
246     {
247         EOObserverCenter.addObserver( observer, element );
248         super.add( index, element );
249     }
250     
251 	public boolean add(Object o)
252     {
253         EOObserverCenter.addObserver( observer, o );
254         return super.add(o);
255     }
256 
257 	public boolean addAll(Collection coll) 
258     {
259         Iterator it = coll.iterator();
260         while ( it.hasNext() )
261         {
262             EOObserverCenter.addObserver( observer, it.next() );
263         }
264         return super.addAll(coll);
265     }
266 
267 	public boolean addAll(int index, Collection c) 
268     {
269         Iterator it = c.iterator();
270         while ( it.hasNext() )
271         {
272             EOObserverCenter.addObserver( observer, it.next() );
273         }
274         return super.addAll( index, c );
275     }
276     
277 	public void clear() 
278     {
279         Iterator it = iterator();
280         while ( it.hasNext() )
281         {
282             EOObserverCenter.removeObserver( observer, it.next() );
283         }
284         super.clear();
285     }
286 
287 	public Object remove(int index) 
288     {
289         EOObserverCenter.removeObserver( observer, get(index) );
290         return super.remove( index );
291     }
292     
293 	public boolean remove(Object o) 
294     {
295         EOObserverCenter.removeObserver( observer, o );
296         return super.remove(o);
297     }
298 
299 	public boolean removeAll(Collection coll) 
300     {
301         Iterator it = coll.iterator();
302         while ( it.hasNext() )
303         {
304             EOObserverCenter.removeObserver( observer, it.next() );
305         }
306         return super.removeAll(coll);
307     }
308 
309 	public boolean retainAll(Collection coll) 
310     {
311         throw new UnsupportedOperationException();
312     }
313 
314     public Object set(int index, Object element) 
315     {
316         EOObserverCenter.removeObserver( observer, get(index) );
317         EOObserverCenter.addObserver( observer, element );
318         return super.set( index, element );
319     }
320 }
321 
322 /*
323  * $Log$
324  * Revision 1.2  2006/02/16 16:47:14  cgruber
325  * Move some classes in to "internal" packages and re-work imports, etc.
326  *
327  * Also use UnsupportedOperationExceptions where appropriate, instead of WotonomyExceptions.
328  *
329  * Revision 1.1  2006/02/16 13:19:57  cgruber
330  * Check in all sources in eclipse-friendly maven-enabled packages.
331  *
332  * Revision 1.1  2002/10/24 21:15:35  mpowers
333  * New implementations of NSArray and subclasses.
334  *
335  * Revision 1.1  2001/02/20 16:38:55  mpowers
336  * MasterDetailAssociations now observe their controlled display group's
337  * objects for changes to that the parent object will be marked as updated.
338  * Before, only inserts and deletes to an object's items are registered.
339  * Also, moved ObservableArray to package access.
340  *
341  * Revision 1.1  2001/01/24 14:37:24  mpowers
342  * Contributing a delegate useful for debugging.
343  *
344  *
345  */
346