2009/05/20 - Apache Shale has been retired.

For more information, please explore the Attic.

View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to you under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.shale.dialog.base;
19  
20  import java.util.ArrayList;
21  import java.util.List;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.apache.shale.dialog.DialogContext;
26  import org.apache.shale.dialog.DialogContextListener;
27  
28  /***
29   * <p>Convenience abstract {@link DialogContext} implementation.
30   * Provides listener registration and convenience event firing methods.
31   * Subclasses are expected to be serializable.</p>
32   *
33   * @since 1.0.4
34   */
35  public abstract class AbstractDialogContext implements DialogContext {
36  
37  
38      // -------------------------------------------------------------- Properties
39  
40  
41      /***
42       * The list of all registered {@link DialogContextListener}s for this
43       * {@link DialogContext}.
44       */
45      private List listeners = new ArrayList();
46  
47  
48      /***
49       * <p>The <code>Log</code> instance for this class.</p>
50       */
51      private transient Log log;
52  
53  
54      // ---------------------------------------------------- Listener Bookkeeping
55  
56  
57      /***
58       * Register given {@link DialogContextListener} for this {@link DialogContext}.
59       * Listener cannot be <code>null</code>.
60       *
61       * @param listener The {@link DialogContextListener} instance.
62       */
63      public void addDialogContextListener(DialogContextListener listener) {
64  
65          if (listener == null) {
66              throw new IllegalArgumentException("Cannot register null DialogContextListener");
67          }
68  
69          synchronized (listeners) {
70              if (listeners.contains(listener)) {
71                  throw new IllegalArgumentException("DialogContextListener already registered");
72              }
73              listener.setDialogContext(this); // attach self reference
74              listeners.add(listener);
75          }
76      }
77  
78  
79      /***
80       * Return the set of currently registered {@link DialogContextListener}s.
81       */
82      public DialogContextListener[] getDialogContextListeners() {
83  
84          synchronized (listeners) {
85              return (DialogContextListener[])
86                listeners.toArray(new DialogContextListener[listeners.size()]);
87          }
88  
89      }
90  
91  
92      /***
93       * Remove this previously registered {@link DialogContextListener} for this
94       * {@link DialogContext}. The listener will no longer receive any
95       * associated callbacks.
96       *
97       * @param listener The {@link DialogContextListener} instance.
98       */
99      public void removeDialogContextListener(DialogContextListener listener) {
100 
101         if (listener == null) {
102             throw new IllegalArgumentException("Cannot remove null DialogContextListener");
103         }
104 
105         boolean removed;
106         synchronized (listeners) {
107             removed = listeners.remove(listener);
108         }
109         if (removed) {
110             listener.setDialogContext(null); // detach self reference
111         }
112 
113     }
114 
115 
116     // -------------------- Utilities for firing DialogContextListener callbacks
117 
118 
119     /***
120      * Inform all registered {@link DialogContextListener}s that the dialog
121      * instance has begun execution.
122      *
123      */
124     protected void fireOnStart() {
125 
126         DialogContextListener[] listeners = getDialogContextListeners();
127         for (int i = 0; i < listeners.length; i++) {
128             listeners[i].onStart();
129         }
130 
131     }
132 
133 
134     /***
135      * Inform all registered {@link DialogContextListener}s that the dialog
136      * instance has finished execution normally.
137      *
138      */
139     protected void fireOnStop() {
140 
141         DialogContextListener[] listeners = getDialogContextListeners();
142         for (int i = 0; i < listeners.length; i++) {
143             listeners[i].onStop();
144         }
145 
146     }
147 
148 
149     /***
150      * Inform all registered {@link DialogContextListener}s that the dialog
151      * instance has encountered an unexpected error condition. The exception
152      * is first logged for archival.
153      *
154      * @param exception A potentially implementation specific exception
155      *                  during the execution of this dialog instance
156      */
157     protected void fireOnException(Exception exception) {
158 
159         log().error(exception.getMessage(), exception);
160 
161         DialogContextListener[] listeners = getDialogContextListeners();
162         for (int i = 0; i < listeners.length; i++) {
163             listeners[i].onException(exception);
164         }
165 
166     }
167 
168 
169     /***
170      * Inform all registered {@link DialogContextListener}s that the dialog instance
171      * execution has entered a particular state.
172      *
173      * @param stateId Implementation specific identifier of the state
174      *                that has been entered
175      */
176     protected void fireOnEntry(String stateId) {
177 
178         DialogContextListener[] listeners = getDialogContextListeners();
179         for (int i = 0; i < listeners.length; i++) {
180             listeners[i].onEntry(stateId);
181         }
182 
183     }
184 
185 
186     /***
187      * Inform all registered {@link DialogContextListener}s that the dialog instance
188      * execution has exited a particular state.
189      *
190      * @param stateId Implementation specific identifier of the state
191      *                that has been exited
192      */
193     protected void fireOnExit(String stateId) {
194 
195         DialogContextListener[] listeners = getDialogContextListeners();
196         for (int i = 0; i < listeners.length; i++) {
197             listeners[i].onExit(stateId);
198         }
199 
200     }
201 
202 
203     /***
204      * Inform all registered {@link DialogContextListener}s that the dialog instance
205      * execution has followed a particular transition.
206      *
207      * @param fromStateId Implementation specific identifier of the source
208      *                    state for the transition that has been followed
209      * @param toStateId Implementation specific identifier of the target
210      *                  state for the transition that has been followed
211      */
212     protected void fireOnTransition(String fromStateId, String toStateId) {
213 
214         DialogContextListener[] listeners = getDialogContextListeners();
215         for (int i = 0; i < listeners.length; i++) {
216             listeners[i].onTransition(fromStateId, toStateId);
217         }
218 
219     }
220 
221 
222     /***
223      * <p>Return the <code>Log</code> instance for this class.</p>
224      */
225     private Log log() {
226 
227         if (log == null) {
228             log = LogFactory.getLog(AbstractDialogContext.class);
229         }
230         return log;
231 
232     }
233 
234 }