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

Quick Search    Search Deep

Source code: com/phoenixst/plexus/ObservableGraphWrapper.java


1   /*
2    *  $Id: ObservableGraphWrapper.java,v 1.18 2003/11/04 20:01:11 rconner Exp $
3    *
4    *  Copyright (C) 1994-2003 by Phoenix Software Technologists,
5    *  Inc. and others.  All rights reserved.
6    *
7    *  THIS PROGRAM AND DOCUMENTATION IS PROVIDED UNDER THE TERMS OF THE
8    *  COMMON PUBLIC LICENSE ("AGREEMENT") WHICH ACCOMPANIES IT.  ANY
9    *  USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES
10   *  RECIPIENT'S ACCEPTANCE OF THE AGREEMENT.
11   *
12   *  The license text can also be found at
13   *    http://opensource.org/licenses/cpl.php
14   */
15  
16  package com.phoenixst.plexus;
17  
18  import java.util.*;
19  
20  
21  /**
22   *  A wrapper around a {@link Graph} so that it can be watched for
23   *  structural changes.  <strong>Note:</strong> the {@link
24   *  Traverser#remove} method on <code>Traversers</code> created by
25   *  this class will only work if the <code>Traversers</code> created
26   *  by the wrapped <code>Graph</code> can tolerate having edges
27   *  removed while the traversal is in progress.
28   *
29   *  @version    $Revision: 1.18 $
30   *  @author     Ray A. Conner
31   *
32   *  @since      1.0
33   */
34  public class ObservableGraphWrapper extends GraphWrapper
35      implements ObservableGraph
36  {
37  
38      private transient List listeners;
39      private transient GraphListener[] listenerArray;
40  
41  
42      ////////////////////////////////////////
43      // Constructor
44      ////////////////////////////////////////
45  
46  
47      /**
48       *  Creates a new <code>ObservableGraphWrapper</code>.
49       */
50      public ObservableGraphWrapper( Graph g )
51      {
52          super( g );
53      }
54  
55  
56  
57      ////////////////////////////////////////
58      // Protected wrap/unwrap methods
59      ////////////////////////////////////////
60  
61  
62      protected Iterator wrapNodeIterator( Iterator nodeIter )
63      {
64          return new ObservableNodeIteratorWrapper( nodeIter );
65      }
66  
67  
68      protected Iterator wrapEdgeIterator( Iterator edgeIter )
69      {
70          return new ObservableEdgeIteratorWrapper( edgeIter );
71      }
72  
73  
74      protected Traverser wrapTraverser( Traverser traverser )
75      {
76          return new ObservableTraverserWrapper( traverser );
77      }
78  
79  
80      ////////////////////////////////////////
81      // Node removal helper method
82      ////////////////////////////////////////
83  
84  
85      protected void removeIncidentEdges( Object node )
86      {
87          Traverser t = traverser( node );
88          while( t.hasNext() ) {
89              t.next();
90              t.removeEdge();
91          }
92      }
93  
94  
95      ////////////////////////////////////////
96      // Graph methods
97      ////////////////////////////////////////
98  
99  
100     public boolean addNode( Object node )
101     {
102         if( super.addNode( node ) ) {
103             fireNodeAdded( node );
104             return true;
105         } else {
106             return false;
107         }
108     }
109 
110 
111     public boolean removeNode( Object node )
112     {
113         if( !super.containsNode( node ) ) {
114             return false;
115         }
116         removeIncidentEdges( node );
117         // Even though we shouldn't have to, check the return value
118         // from removeNode() anyway, since someone else may have
119         // nuked it and we don't want to send out duplicate events.
120         if( super.removeNode( node ) ) {
121             fireNodeRemoved( node );
122         }
123         return true;
124     }
125 
126 
127     public Edge addEdge( Object object, Object tail, Object head )
128     {
129         Edge edge = super.addEdge( object, tail, head );
130         if( edge != null ) {
131             fireEdgeAdded( edge );
132         }
133         return edge;
134     }
135 
136 
137     public boolean removeEdge( Edge edge )
138     {
139         if( super.removeEdge( edge ) ) {
140             fireEdgeRemoved( edge );
141             return true;
142         } else {
143             return false;
144         }
145     }
146 
147 
148     public void clear()
149     {
150         Iterator nodeIter = nodeIterator();
151         while( nodeIter.hasNext() ) {
152             nodeIter.next();
153             nodeIter.remove();
154         }
155     }
156 
157 
158     ////////////////////////////////////////
159     // ObservableGraph methods
160     ////////////////////////////////////////
161 
162 
163     public synchronized void addGraphListener( GraphListener listener )
164     {
165         if( listeners == null ) {
166             listeners = new ArrayList();
167         }
168         listeners.add( listener );
169         listenerArray = null;
170     }
171 
172 
173     public synchronized void removeGraphListener( GraphListener listener )
174     {
175         if( listeners == null ) {
176             return;
177         }
178         listeners.remove( listener );
179         listenerArray = null;
180     }
181 
182 
183     ////////////////////////////////////////
184     // Event firing methods
185     ////////////////////////////////////////
186 
187 
188     /**
189      *
190      */
191     protected final GraphListener[] createListenerArray()
192     {
193         if( listeners == null || listeners.isEmpty() ) {
194             return null;
195         }
196         if( listenerArray == null ) {
197             listenerArray = new GraphListener[ listeners.size() ];
198             listenerArray = (GraphListener[]) listeners.toArray( listenerArray );
199         }
200         return listenerArray;
201     }
202 
203 
204     /**
205      *
206      */
207     protected synchronized void fireNodeAdded( Object node )
208     {
209         GraphListener[] array = createListenerArray();
210         if( array != null ) {
211             GraphEvent event = new GraphEvent( this, node );
212             for( int i = 0; i < array.length; i++ ) {
213                 array[i].nodeAdded( event );
214             }
215         }
216     }
217 
218 
219     /**
220      *
221      */
222     protected synchronized void fireNodeRemoved( Object node )
223     {
224         GraphListener[] array = createListenerArray();
225         if( array != null ) {
226             GraphEvent event = new GraphEvent( this, node );
227             for( int i = 0; i < array.length; i++ ) {
228                 array[i].nodeRemoved( event );
229             }
230         }
231     }
232 
233 
234     /**
235      *
236      */
237     protected synchronized void fireEdgeAdded( Edge edge )
238     {
239         GraphListener[] array = createListenerArray();
240         if( array != null ) {
241             GraphEvent event = new GraphEvent( this, edge );
242             for( int i = 0; i < array.length; i++ ) {
243                 array[i].edgeAdded( event );
244             }
245         }
246     }
247 
248 
249     /**
250      *
251      */
252     protected synchronized void fireEdgeRemoved( Edge edge )
253     {
254         GraphListener[] array = createListenerArray();
255         if( array != null ) {
256             GraphEvent event = new GraphEvent( this, edge );
257             for( int i = 0; i < array.length; i++ ) {
258                 array[i].edgeRemoved( event );
259             }
260         }
261     }
262 
263 
264     ////////////////////////////////////////
265     // Private iterator wrapper classes
266     ////////////////////////////////////////
267 
268 
269     /**
270      *
271      */
272     private class ObservableNodeIteratorWrapper
273         extends NodeIteratorWrapper
274     {
275         private Object currentNode;
276         private boolean isCurrentValid = false;
277 
278         private ObservableNodeIteratorWrapper( Iterator i )
279         {
280             super( i );
281         }
282 
283         public Object next()
284         {
285             currentNode = super.next();
286             isCurrentValid = true;
287             return currentNode;
288         }
289 
290         public void remove()
291         {
292             if( !isCurrentValid ) {
293                 throw new IllegalStateException();
294             }
295             removeIncidentEdges( currentNode );
296             super.remove();
297             fireNodeRemoved( currentNode );
298             isCurrentValid = false;
299         }
300     }
301 
302 
303     /**
304      *
305      */
306     private class ObservableEdgeIteratorWrapper
307         extends EdgeIteratorWrapper
308     {
309         private Edge currentEdge;
310 
311         private ObservableEdgeIteratorWrapper( Iterator i )
312         {
313             super( i );
314         }
315 
316         public Object next()
317         {
318             currentEdge = (Edge) super.next();
319             return currentEdge;
320         }
321 
322         public void remove()
323         {
324             super.remove();
325             fireEdgeRemoved( currentEdge );
326         }
327     }
328 
329 
330     /**
331      *
332      */
333     private class ObservableTraverserWrapper
334         extends TraverserWrapper
335     {
336         protected Object currentNode;
337         private boolean isCurrentValid;
338 
339         protected ObservableTraverserWrapper( Traverser i )
340         {
341             super( i );
342             isCurrentValid = false;
343         }
344 
345         public Object next()
346         {
347             currentNode = super.next();
348             isCurrentValid = true;
349             return currentNode;
350         }
351 
352         public void remove()
353         {
354             if( !isCurrentValid ) {
355                 throw new IllegalStateException();
356             }
357             removeIncidentEdges( currentNode );
358             super.remove();
359             fireNodeRemoved( currentNode );
360             isCurrentValid = false;
361         }
362 
363         public void removeEdge()
364         {
365             Edge edge = super.getEdge();
366             super.removeEdge();
367             fireEdgeRemoved( edge );
368         }
369     }
370 
371 }