KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > barracuda > core > event > DefaultDispatchQueue


1 /*
2  * Copyright (C) 2003 Christian Cryder [christianc@granitepeaks.com]
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * $Id: DefaultDispatchQueue.java,v 1.11 2004/02/01 05:16:28 christianc Exp $
19  */

20 package org.enhydra.barracuda.core.event;
21
22 import java.io.*;
23 import java.util.*;
24
25 import org.apache.log4j.*;
26
27 import org.enhydra.barracuda.plankton.data.*;
28
29 /**
30  * <p>The DispatchQueue as a relatively shortlived structure...the
31  * Queue would be created by the dispatcher, and it would be discarded
32  * when the events have been delivered. It should be made available to
33  * the listeners, however, so that they can add events to the queue
34  * if they'd like.
35  *
36  * <p>While the DispatchQueue interface views the queue as one list of events,
37  * the DefaultDispatchQueue is designed to be aware of two different kinds
38  * of events: Control events, and View events. This corresponds nicely
39  * with both the Http Req/Response model and the Model 2 Controller/View
40  * distinction.
41  *
42  * <p>This means that when you add an event to the queue, internally gets
43  * filtered into either a control list or a view list. Consequently,
44  * when iterating through the queue, you will always get all control events
45  * first, then you will get all view events. The DefaultEventDispatcher
46  * makes use of this distinction to implement a 2 phase event dispatch:
47  * request events are dispatched first, followed by response events.
48  *
49  * <p>The queue can also be used for a single phased dispatch by setting
50  * requiresResponse = false.
51  *
52  * <p>The queue is smart enough so that as you add events to it, duplicate
53  * events are collapsed together and redundancies are eliminated (ie. if
54  * I add 3 RepaintView events, they would be combined into one, which appears
55  * at the end of the queue).
56  *
57  * <p>As a final note, observe that not all of the methods are public. This
58  * is to limit BaseEventListener access: listeners add events to the queue,
59  * see what events are in the queue, and even mark them handled. But they
60  * cannot actually remove events from the queue. That duty belongs to the
61  * Event Dispatcher, which of necessity must be in the same package as
62  * the DispatchQueue in order to be able to access all methods.
63  */

64 public class DefaultDispatchQueue implements DispatchQueue {
65
66     //public vars...eventually, these should probably be final
67
protected static final Logger logger = Logger.getLogger(DefaultDispatchQueue.class.getName());
68
69     //private vars
70
protected boolean requiresResponse = false;
71     protected boolean responseHandled = false;
72     protected List controlList = new ArrayList();
73     protected List viewList = new ArrayList();
74     protected List procList = new ArrayList();
75
76     /**
77      * Public noargs constructor. A queue must be defined as requiring a
78      * response or not. This value can not be changed during the life of
79      * the queue. Typically, any queue created to service an HTTP request
80      * will set this value to true.
81      *
82      * @param irequiresResponse true if this queue requires a response
83      */

84     public DefaultDispatchQueue(boolean irequiresResponse) {
85 //csc_011504_1 requiresResponse = irequiresResponse;
86
setRequiresResponse(irequiresResponse); //csc_011504_1
87
}
88
89     /**
90      * Does this queue require a response?
91      *
92      * @return true if this queue requires a response
93      */

94     public boolean requiresResponse() {
95         return requiresResponse;
96     }
97
98     //csc_011504_1 - added
99
/**
100      * Programatically tell the dispatcher that a response is required
101      *
102      * @param true if a response is required
103      */

104     public void setRequiresResponse(boolean val) {
105         if (logger.isDebugEnabled()) logger.debug("Setting requiresResponse:"+val);
106         requiresResponse = val;
107     }
108
109
110     /**
111      * Has the response for this queue been handled?
112      *
113      * @return true if the response has been handled
114      */

115     public boolean responseHandled() {
116         return responseHandled;
117     }
118
119     /**
120      * Mark the response as handled
121      *
122      * @param val whether or not the response has been handled
123      */

124     public void setResponseHandled(boolean val) {
125         if (logger.isDebugEnabled()) logger.debug("Setting responseHandled:"+val);
126         responseHandled = val;
127     }
128
129     /**
130      * Removes all events from the current dispatch queue
131      */

132     void resetQueue() {
133         if (logger.isDebugEnabled()) logger.debug("Resetting queue");
134         controlList = new ArrayList();
135         viewList = new ArrayList();
136         procList = new ArrayList();
137     }
138
139     /**
140      * Adds an event to the queue. When this happens, we first remove
141      * any existing events in the queue that this event .equals(), and
142      * then this event is added. This has the effect of collapsing
143      * duplicates.
144      *
145      * @param baseEvent the event to be added to the queue
146      */

147     public void addEvent(BaseEvent baseEvent) {
148         if (baseEvent==null) return;
149         removeEvent(baseEvent);
150         if (baseEvent instanceof ViewEvent) {
151             if (logger.isInfoEnabled()) logger.info("Adding ViewEvent:"+baseEvent);
152             viewList.add(baseEvent);
153         } else {
154             if (logger.isInfoEnabled()) logger.info("Adding ControlEvent:"+baseEvent);
155             controlList.add(baseEvent);
156         }
157     }
158
159     /**
160      * Remove all instances of an event from the queue that the
161      * incoming event .equals()
162      *
163      * @param baseEvent the event to be removed from the queue
164      */

165     void removeEvent(BaseEvent baseEvent) {
166         if (baseEvent==null) return;
167         if (logger.isInfoEnabled()) logger.info("Removing all instances of:"+baseEvent);
168         List list = (baseEvent instanceof ViewEvent ? viewList : controlList);
169         Object JavaDoc items[] = list.toArray();
170         for (int max=items.length, i=max-1; i>-1; i--) {
171             if (baseEvent.equals(items[i])) list.remove(i);
172         }
173     }
174
175     /**
176      * Are there any more ControlEvents in this queue
177      */

178     boolean hasNextControlEvent() {
179         return (controlList.size()>0);
180     }
181
182     /**
183      * Are there any more ViewEvents in this queue
184      */

185     boolean hasNextViewEvent() {
186         return (viewList.size()>0);
187     }
188
189     /**
190      * Take a peek at the next ControlEvent without actually removing it
191      *
192      * @return the next control event in the queue
193      */

194     BaseEvent peekNextControlEvent() {
195         return (hasNextControlEvent() ? (BaseEvent) controlList.get(0) : null);
196     }
197     
198     /**
199      * Take a peek at the next ViewEvent without actually removing it
200      *
201      * @return the next view event in the queue
202      */

203     ViewEvent peekNextViewEvent() {
204         return (hasNextViewEvent() ? (ViewEvent) viewList.get(0) : null);
205     }
206     
207     /**
208      * Get the next ControlEvent, effectively removing it from the queue
209      *
210      * @return the next control event in the queue
211      */

212     BaseEvent getNextControlEvent() {
213         BaseEvent controlEvent = peekNextControlEvent();
214         controlList.remove(0);
215         procList.add(controlEvent);
216         if (logger.isInfoEnabled()) logger.info("Getting next ControlEvent:"+controlEvent);
217         return controlEvent;
218     }
219     
220     /**
221      * Get the next ViewEvent, effectively removing it from the queue
222      *
223      * @return the next view event in the queue
224      */

225     ViewEvent getNextViewEvent() {
226         ViewEvent viewEvent = peekNextViewEvent();
227         viewList.remove(0);
228         procList.add(viewEvent);
229         if (logger.isInfoEnabled()) logger.info("Getting next ViewEvent:"+viewEvent);
230         return viewEvent;
231     }
232     
233     /**
234      * get the number of events remaining in the queue
235      *
236      * @return the number of events remaining in the queue
237      */

238     public int numberOfEventsRemaining() {
239         return controlList.size() + viewList.size();
240     }
241
242     /**
243      * List all events remaining in the queue (Request events first, then
244      * Response events)
245      *
246      * @return a list of all events remaining in the queue
247      */

248     public List listRemainingEvents() {
249         ArrayList list = new ArrayList(controlList);
250         list.addAll(viewList);
251         return list;
252     }
253     
254     /**
255      * List the ControlEvents
256      *
257      * @return a list of all request events remaining in the queue
258      */

259     List listControlEvents() {
260         return new ArrayList(controlList);
261     }
262
263     /**
264      * List the ViewEvents
265      *
266      * @return a list of all response events remaining in the queue
267      */

268     List listViewEvents() {
269         return new ArrayList(viewList);
270     }
271
272     /**
273      * get the number of events that have been processed
274      *
275      * @return the number of events processed in the queue
276      */

277     public int numberOfEventsProcessed() {
278         return procList.size();
279     }
280     
281     /**
282      * List events which have already been processed through the queue
283      *
284      * @return a list of all events processed in the queue
285      */

286     public List listProcessedEvents() {
287         return new ArrayList(procList);
288     }
289     
290     /**
291      * mark all events handled
292      */

293     void markEventsHandled() {
294         if (logger.isDebugEnabled()) logger.debug("Marking all events handled");
295         Iterator it = null;
296         for (int i=0; i<2; i++) {
297             List curList = (i==0 ? controlList : viewList);
298             it = curList.iterator();
299             while (it.hasNext()) {
300                 BaseEvent be = (BaseEvent) it.next();
301                 be.setHandled(true);
302             }
303         }
304     }
305     
306
307     //-------------------- Debugging -----------------------------
308
/**
309      * Dunp event queue to console for debugging purposes.
310      *
311      * @param targetDepth the depth at which we should start
312      * printing debug information
313      */

314     public void dumpEventQueueToConsole(int targetDepth) {
315         if (logger.isDebugEnabled()) {
316             logger.debug("Dumping Event Queue contents:");
317             logger.debug("Request Events:");
318             CollectionsUtil.printStackTrace(controlList, targetDepth+1, logger, null);
319             logger.debug("Response Events:");
320             CollectionsUtil.printStackTrace(viewList, targetDepth+1, logger, null);
321         }
322     }
323 }
324
Popular Tags