View Javadoc

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 }