Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/progeeks/meta/AbstractListMutator.java


1   /*
2    * $Id: AbstractListMutator.java,v 1.1 2003/08/27 21:39:23 pspeed Exp $
3    *
4    * Copyright (c) 2001-2002, Paul Speed
5    * All rights reserved.
6    *
7    * Redistribution and use in source and binary forms, with or without
8    * modification, are permitted provided that the following conditions
9    * are met:
10   *
11   * 1) Redistributions of source code must retain the above copyright notice,
12   *    this list of conditions and the following disclaimer.
13   * 2) Redistributions in binary form must reproduce the above copyright
14   *    notice, this list of conditions and the following disclaimer in the
15   *    documentation and/or other materials provided with the distribution.
16   * 3) Neither the names "Progeeks", "Meta-JB", nor the names of its contributors
17   *    may be used to endorse or promote products derived from this software
18   *    without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   */
32  
33  package org.progeeks.meta;
34  
35  import java.beans.*;
36  import java.util.*;
37  
38  import org.progeeks.meta.*;
39  
40  /**
41   *  <p>Abstract implementation of ListMutator providing basic
42   *  functionality for dealing with List values.</p>
43   *
44   *  <p>Subclasses are required to implement at least the
45   *  get(int) and size() methods for read-only access.</p>
46   *
47   *  <p>For a modifiable list, set(int, object) should be overriden
48   *  and for a resizble list, add(object) and remove(int) should be
49   *  overridden.  Otherwise, these methods throw UnsupportedOperation
50   *  exception.</p>
51   *
52   *  <p>To support change notification, subclasses must provide
53   *  an implementation of the firePropertyChangeEvent() method.</p>
54   *
55   *  Note: this may eventually move to the meta package
56   *        and be re-extended here just to provide the ability
57   *        to do external change notifications.
58   *
59   *  @version   $Revision: 1.1 $
60   *  @author    Paul Speed
61   */
62  public abstract class AbstractListMutator implements ListMutator
63  {
64      /**
65       *  Returns the number of elements in the list value.
66       */
67      public abstract int size();
68  
69      /**
70       *  Returns the object at the specified location.
71       */
72      public abstract Object get( int index );
73  
74      /**
75       *  Adds the object to the list value at the specified index.
76       *
77       *  @throws UnsupportedOperationException if the list value does
78       *          not support insertions.
79       */
80      public void add( int index, Object object )
81      {
82          throw new UnsupportedOperationException();
83      }
84  
85      /**
86       *  Replaces the value at the specified location.
87       *
88       *  @throws UnsupportedOperationException if the list value does
89       *          not support replacing elements.
90       */
91      public Object set( int index, Object object )
92      {
93          throw new UnsupportedOperationException();
94      }
95  
96      /**
97       *  Removes the object at the specified location and returns
98       *  the locations value prior to removal.
99       *
100      *  @throws UnsupportedOperationException if the list value does
101      *          not support removes.
102      */
103     public Object remove( int index )
104     {
105         throw new UnsupportedOperationException();
106     }
107 
108     /**
109      *  Returns an iterator over the elements in this list value.
110      */
111     public Iterator iterator()
112     {
113         return( new IndexIterator() );
114     }
115 
116     /**
117      *  Adds the object to the list value, returning true
118      *  if the contents of the list actually changed as a result
119      *  of the operation.
120      *
121      *  @throws UnsupportedOperationException if the list value does
122      *          not support adds.
123      */
124     public boolean add( Object object )
125     {
126         add( size(), object );
127 
128         return( true );
129     }
130 
131     /**
132      *  Removes the specified object from the list value, returning true
133      *  if the list contents were modified as a result of the action.
134      *
135      *  @throws UnsupportedOperationException if the list value does
136      *          not support removes.
137      */
138     public boolean remove( Object object )
139     {
140         int index = 0;
141         for( Iterator i = iterator(); i.hasNext(); index++ )
142             {
143             Object element = i.next();
144             if( object == element || (object != null && object.equals(element)) )
145                 {
146                 remove( index );
147                 return( true );
148                 }
149             }
150         return( false );
151     }
152 
153     /**
154      *  Clears the contents of the list value.
155      *
156      *  @throws UnsupportedOperationException if the list value does
157      *          not support being cleared.
158      */
159     public void clear()
160     {
161         while( size() > 0 )
162             remove( 0 );
163     }
164 
165     /**
166      *  Implemented by subclasses to deliver a change event to
167      *  the appropriately registered listeners.
168      */
169     protected abstract void firePropertyChangeEvent( PropertyChangeEvent event );
170 
171     /**
172      *  Sends an event to interested listeners that this property
173      *  has had elements inserted.  These methods are public so that
174      *  changes made external to the internal data structures can still
175      *  cause notifications.
176      */
177     public void fireElementsInserted( int first, int last )
178     {
179         PropertyChangeEvent event = new ListPropertyChangeEvent( getParentObject(),
180                                                                  getPropertyName(),
181                                                                  getValue(), first, last,
182                                                                  ListPropertyChangeEvent.INSERT );
183         firePropertyChangeEvent( event );
184     }
185 
186     /**
187      *  Sends an event to interested listeners that this property
188      *  has had elements inserted.  These methods are public so that
189      *  changes made external to the internal data structures can still
190      *  cause notifications.
191      */
192     public void fireElementsModified( int first, int last )
193     {
194         PropertyChangeEvent event = new ListPropertyChangeEvent( getParentObject(),
195                                                                  getPropertyName(),
196                                                                  getValue(), first, last,
197                                                                  ListPropertyChangeEvent.UPDATE );
198         firePropertyChangeEvent( event );
199     }
200 
201     /**
202      *  Sends an event to interested listeners that this property
203      *  has had elements inserted.  These methods are public so that
204      *  changes made external to the internal data structures can still
205      *  cause notifications.
206      */
207     public void fireElementsRemoved( int first, int last )
208     {
209         PropertyChangeEvent event = new ListPropertyChangeEvent( getParentObject(),
210                                                                  getPropertyName(),
211                                                                  getValue(), first, last,
212                                                                  ListPropertyChangeEvent.DELETE );
213         firePropertyChangeEvent( event );
214     }
215 
216     private class IndexIterator implements Iterator
217     {
218         /*
219          *  Note: no concurrent modification checks are done.
220          *        This needs to be added.
221          */
222 
223         /**
224          *  Next element that iwll be returned by next().
225          */
226         int nextIndex = 0;
227 
228         /**
229          *  Last index returned by next().
230          */
231         int lastIndex = -1;
232 
233         public boolean hasNext()
234         {
235             return( nextIndex != size() );
236         }
237 
238         public Object next()
239         {
240             try
241                 {
242                 Object ret = get( nextIndex );
243                 lastIndex = nextIndex;
244                 nextIndex++;
245 
246                 return( ret );
247                 }
248             catch( IndexOutOfBoundsException e )
249                 {
250                 throw new NoSuchElementException( String.valueOf(nextIndex) );
251                 }
252         }
253 
254         public void remove()
255         {
256             if( lastIndex == -1 )
257                 throw new IllegalStateException( "remove() called before next()." );
258 
259             try
260                 {
261                 AbstractListMutator.this.remove( lastIndex );
262                 if( lastIndex < nextIndex )
263                     nextIndex--;
264                 lastIndex = -1;
265                 }
266             catch( IndexOutOfBoundsException e )
267                 {
268                 // Can't really be anything else at this point.
269                 throw new ConcurrentModificationException();
270                 }
271         }
272     }
273 }
274