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 }