1 //----------------------------------------------------------------------
2 //
3 // PerfectJPattern: "Design patterns are good but components are better!"
4 // Subject.java Copyright (c) 2009 Giovanni Azua Garcia
5 // bravegag@hotmail.com
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License
9 // as published by the Free Software Foundation; either version 3
10 // of the License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, see <http://www.gnu.org/licenses/>.
19 //
20 //----------------------------------------------------------------------
21 package org.perfectjpattern.core.behavioral.observer;
22
23 import java.util.*;
24
25 import org.apache.commons.lang.*;
26 import org.perfectjpattern.core.api.behavioral.observer.*;
27 import org.slf4j.*;
28
29
30 /**
31 * Base core implementation of <code>ISubject</code> interface.
32 * <br/>
33 *
34 * @see ISubject
35 *
36 * @param <E> Type of event data this <code>ISubject</code>
37 * notifies with.
38 *
39 * @author <a href="mailto:bravegag@hotmail.com">Giovanni Azua</a>
40 * @version $Revision: 1.0 $ $Date: Jun 18, 2007 9:06:39 PM $
41 */
42 public
43 class Subject<E>
44 implements ISubject<E>
45 {
46 //------------------------------------------------------------------------
47 // public
48 //------------------------------------------------------------------------
49 /**
50 * {@inheritDoc}
51 */
52 public void
53 attach(IObserver<E>... anObservers)
54 {
55 Validate.notNull(anObservers, "'anObservers' must not be null");
56
57 theObservers.addAll(Arrays.asList(anObservers));
58 }
59
60 //------------------------------------------------------------------------
61 /**
62 * {@inheritDoc}
63 */
64 public void
65 clear()
66 {
67 theObservers.clear();
68 }
69
70 //------------------------------------------------------------------------
71 /**
72 * {@inheritDoc}
73 */
74 public void
75 detach(IObserver<E>... anObservers)
76 {
77 Validate.notNull(anObservers, "'anObservers' must not be null");
78
79 theObservers.removeAll(Arrays.asList(anObservers));
80 }
81
82 //------------------------------------------------------------------------
83 /**
84 * {@inheritDoc}
85 */
86 @SuppressWarnings("unchecked")
87 public void
88 notifyObservers(E anEventData)
89 {
90 Validate.notNull(anEventData, "'anEventData' must not be null");
91
92 IObserver<E>[] myObservers = theObservers.toArray(EMPTY_ARRAY);
93
94 for (IObserver<E> myObserver : myObservers)
95 {
96 try
97 {
98 myObserver.update(anEventData);
99 }
100 //CHECKSTYLE:OFF
101 catch (Throwable anException)
102 //CHECKSTYLE:ON
103 {
104 // faulty Observer instances are automatically detached
105 detach(myObserver);
106
107 theLogger.error("Observer '" + System.identityHashCode(
108 myObserver) + "' has thrown an unchecked exception on " +
109 "update and has been automatically detached.",
110 anException);
111 }
112 }
113 }
114
115 //------------------------------------------------------------------------
116 /**
117 * {@inheritDoc}
118 */
119 public int
120 size()
121 {
122 return theObservers.size();
123 }
124
125 //------------------------------------------------------------------------
126 // protected
127 //------------------------------------------------------------------------
128 /**
129 * Returns the Observer instances
130 *
131 * @return the Observer instances
132 */
133 protected Collection<IObserver<E>>
134 getObservers()
135 {
136 return Collections.unmodifiableCollection(theObservers);
137 }
138
139 //------------------------------------------------------------------------
140 // members
141 //------------------------------------------------------------------------
142 /**
143 * Collection of <code>IObserver</code> instances.
144 */
145 private final Collection<IObserver<E>> theObservers = new ArrayList<
146 IObserver<E>>();
147
148 /**
149 * Reusable empty array of <code>IObserver</code> so it does not need
150 * to be recreated each time there is a call to
151 * <code>notifyObservers</code>
152 */
153 @SuppressWarnings("unchecked")
154 protected static final IObserver[] EMPTY_ARRAY = new IObserver[0];
155
156 /**
157 * Provides logging services for this class
158 */
159 private final Logger theLogger = LoggerFactory.getLogger(this.getClass());
160 }