001         package com.croftsoft.core.util.pubsub;
002    
003         import com.croftsoft.core.lang.NullArgumentException;
004         import com.croftsoft.core.lang.ex.ExceptionHandler;
005         import com.croftsoft.core.util.ArrayLib;
006    
007         /*********************************************************************
008         * A synchronous Publisher implementation backed by a Subscriber array.
009         *
010         * <p>
011         * In this simple Publisher implementation, message propagation is
012         * synchronous; all of the methods are synchronized and the publish()
013         * method does not return until all Subscribers have been contacted
014         * one-at-a-time and in array order.
015         * </p>
016         *
017         * <p>
018         * Java 1.1 compatible.
019         * </p>
020         *
021         * @see
022         *   Publisher
023         * @see
024         *   Subscriber
025         *
026         * @version
027         *   2002-01-29
028         * @since
029         *   2001-04-04
030         * @author
031         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
032         *********************************************************************/
033    
034         public final class  ArrayPublisher
035           implements Publisher
036         //////////////////////////////////////////////////////////////////////
037         //////////////////////////////////////////////////////////////////////
038         {
039    
040         private final ExceptionHandler   exceptionHandler;
041    
042         private Subscriber [ ]  subscribers;
043    
044         //////////////////////////////////////////////////////////////////////
045         //////////////////////////////////////////////////////////////////////
046    
047         /*********************************************************************
048         * @param  exceptionHandler
049         *
050         *   Handles any Exceptions thrown by Subscriber.receive().
051         *   If null, exception.printStackTrace() will be used by default.
052         *********************************************************************/
053         public  ArrayPublisher (
054           ExceptionHandler  exceptionHandler,
055           Subscriber [ ]    subscribers )
056         //////////////////////////////////////////////////////////////////////
057         {
058           this.exceptionHandler = exceptionHandler;
059    
060           NullArgumentException.check ( this.subscribers = subscribers );
061         }
062    
063         /*********************************************************************
064         * this ( null, new Subscriber [ ] { } );
065         *********************************************************************/
066         public  ArrayPublisher ( )
067         //////////////////////////////////////////////////////////////////////
068         {
069           this ( null, new Subscriber [ ] { } );
070         }
071    
072         //////////////////////////////////////////////////////////////////////
073         //////////////////////////////////////////////////////////////////////
074    
075         /*********************************************************************
076         * @return
077         *   False if the Subscriber was already in the array.
078         *********************************************************************/
079         public synchronized boolean  addSubscriber ( Subscriber  subscriber )
080         //////////////////////////////////////////////////////////////////////
081         {
082           NullArgumentException.check ( subscriber );
083    
084           for ( int  i = subscribers.length - 1; i > -1; i-- )
085           {
086             if ( subscribers [ i ] == subscriber )
087             {
088               return false;
089             }
090           }
091    
092           subscribers
093             = ( Subscriber [ ] ) ArrayLib.append ( subscribers, subscriber );
094    
095           return true;
096         }
097    
098         /*********************************************************************
099         * @return
100         *   False if the Subscriber was not in the array to be removed.
101         *********************************************************************/
102         public synchronized boolean  removeSubscriber (
103           Subscriber  subscriber )
104         //////////////////////////////////////////////////////////////////////
105         {
106           NullArgumentException.check ( subscriber );
107    
108           int  index = -1;
109    
110           for ( int  i = subscribers.length - 1; i > -1; i-- )
111           {
112             if ( subscribers [ i ] == subscriber )
113             {
114               index = i;
115    
116               break;
117             }
118           }
119    
120           if ( index < 0 )
121           {
122             return false;
123           }
124    
125           subscribers
126             = ( Subscriber [ ] ) ArrayLib.remove ( subscribers, index );
127    
128           return true;
129         }
130    
131         //////////////////////////////////////////////////////////////////////
132         //////////////////////////////////////////////////////////////////////
133    
134         public synchronized void  publish ( Object  message )
135         //////////////////////////////////////////////////////////////////////
136         {
137           for ( int  i = 0; i < subscribers.length; i++ )
138           {
139             try
140             {
141               subscribers [ i ].receive ( message );
142             }
143             catch ( Exception  ex )
144             {
145               if ( exceptionHandler != null )
146               {
147                 exceptionHandler.handleException ( ex, subscribers [ i ] );
148               }
149               else
150               {
151                 ex.printStackTrace ( );
152               }
153             }
154           }
155         }
156    
157         public synchronized void  receive ( Object  message )
158         //////////////////////////////////////////////////////////////////////
159         {
160           publish ( message );
161         }
162    
163         //////////////////////////////////////////////////////////////////////
164         //////////////////////////////////////////////////////////////////////
165         }