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="http://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 }