KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > event > DispatchQueue


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20
21 package org.apache.cayenne.event;
22
23 import java.util.ArrayList JavaDoc;
24 import java.util.Collection JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.Map JavaDoc;
28 import java.util.Set JavaDoc;
29 import java.util.WeakHashMap JavaDoc;
30
31 import org.apache.cayenne.event.EventManager.Dispatch;
32 import org.apache.cayenne.util.Invocation;
33
34 /**
35  * Stores a set of Invocation objects, organizing them by sender. Listeners have an option
36  * to receive events for a particular sender or to receive all events. EventManager
37  * creates one DispatchQueue per EventSubject. DispatchQueue is thread-safe - all methods
38  * that read/modify internal collections are synchronized.
39  *
40  * @author Andrus Adamchik
41  * @since 1.1
42  */

43 class DispatchQueue {
44
45     private Set JavaDoc subjectInvocations = new HashSet JavaDoc();
46     private Map JavaDoc invocationsBySender = new WeakHashMap JavaDoc();
47
48     /**
49      * Dispatches event to all listeners in the queue that are registered for this event
50      * and sender.
51      */

52     synchronized void dispatchEvent(Dispatch dispatch) {
53         // dispatch to "any sender" listeners
54
dispatchEvent(subjectInvocations, dispatch);
55
56         // dispatch to the given sender listeners
57
Object JavaDoc sender = dispatch.getSender();
58         dispatchEvent(invocationsForSender(sender, false), dispatch);
59     }
60
61     synchronized void addInvocation(Invocation invocation, Object JavaDoc sender) {
62         if (sender == null) {
63             subjectInvocations.add(invocation);
64         }
65         else {
66             invocationsForSender(sender, true).add(invocation);
67         }
68     }
69
70     synchronized boolean removeInvocations(Object JavaDoc listener, Object JavaDoc sender) {
71
72         // remove only for specific sender
73
if (sender != null) {
74             return removeInvocations(invocationsForSender(sender, false), listener);
75         }
76
77         boolean didRemove = false;
78
79         // remove listener from all collections
80
didRemove = removeInvocations(subjectInvocations, listener);
81
82         Iterator JavaDoc sets = invocationsBySender.values().iterator();
83         while (sets.hasNext()) {
84             Collection JavaDoc senderInvocations = (Collection JavaDoc) sets.next();
85             if (senderInvocations == null) {
86                 continue;
87             }
88
89             Iterator JavaDoc it = senderInvocations.iterator();
90             while (it.hasNext()) {
91                 Invocation invocation = (Invocation) it.next();
92                 if (invocation.getTarget() == listener) {
93                     it.remove();
94                     didRemove = true;
95                 }
96             }
97         }
98
99         return didRemove;
100     }
101
102     private Collection JavaDoc invocationsForSender(Object JavaDoc sender, boolean create) {
103         Collection JavaDoc senderInvocations = (Collection JavaDoc) invocationsBySender.get(sender);
104         if (create && senderInvocations == null) {
105             senderInvocations = new HashSet JavaDoc();
106             invocationsBySender.put(sender, senderInvocations);
107         }
108
109         return senderInvocations;
110     }
111
112     // removes all invocations for a given listener
113
private boolean removeInvocations(Collection JavaDoc invocations, Object JavaDoc listener) {
114         if (invocations == null || invocations.isEmpty()) {
115             return false;
116         }
117
118         boolean didRemove = false;
119
120         Iterator JavaDoc invocationsIt = invocations.iterator();
121         while (invocationsIt.hasNext()) {
122             Invocation invocation = (Invocation) invocationsIt.next();
123             if (invocation.getTarget() == listener) {
124                 invocationsIt.remove();
125                 didRemove = true;
126             }
127         }
128
129         return didRemove;
130     }
131
132     // dispatches event to a list of listeners
133
private void dispatchEvent(Collection JavaDoc invocations, Dispatch dispatch) {
134         if (invocations == null || invocations.isEmpty()) {
135             return;
136         }
137
138         // iterate over copy of the collection as there is a chance a caller would want to
139
// (un)register another listener during event processing
140
Iterator JavaDoc it = new ArrayList JavaDoc(invocations).iterator();
141         while (it.hasNext()) {
142             Invocation invocation = (Invocation) it.next();
143
144             // fire invocation, detect if anything went wrong (e.g. GC'ed invocation
145
// targets)
146
if (!dispatch.fire(invocation)) {
147                 invocations.remove(invocation);
148             }
149         }
150     }
151 }
152
Popular Tags