KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > lib > editor > util > PriorityListenerList


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.lib.editor.util;
21
22 import java.io.IOException JavaDoc;
23 import java.io.ObjectInputStream JavaDoc;
24 import java.io.ObjectOutputStream JavaDoc;
25 import java.io.Serializable JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.EventListener JavaDoc;
28 import java.util.List JavaDoc;
29
30 /**
31  * Listener list that layers the maintained listeners
32  * according to the given priority index.
33  * <br>
34  * Simply said it's an array of listener arrays. The priority index defines
35  * the event listeners array holding all the listeners with the given priority index.
36  *
37  * @author Miloslav Metelka
38  * @since 1.4
39  */

40
41 public class PriorityListenerList<T extends EventListener JavaDoc> implements Serializable JavaDoc {
42     
43     static final long serialVersionUID = 0L;
44     
45     private static final EventListener JavaDoc[] EMPTY_LISTENER_ARRAY = new EventListener JavaDoc[0];
46     
47     private static final EventListener JavaDoc[][] EMPTY_LISTENER_ARRAY_ARRAY = new EventListener JavaDoc[0][];
48
49     private transient T[][] listenersArray;
50     
51     public PriorityListenerList() {
52         listenersArray = emptyTArrayArray();
53     }
54     
55     /**
56      * Add listener with the given priority.
57      *
58      * @param listener listener to be added. If null is passed it is ignored (nothing gets added).
59      * @param priority &gt;=0 index defining priority
60      * with which the listener should be fired.
61      * <br>
62      * The higher the priority the sooner the listener will be fired.
63      * <br>
64      * It's guaranteed that all the listeners with higher priority index will be fired
65      * sooner than listeners with lower priority.
66      * <br>
67      * The number of priority levels should be limited to reasonably
68      * low number.
69      * @throws IndexOutOfBoundsException when priority &lt; 0
70      */

71     public synchronized void add(T listener, int priority) {
72         if (listener == null)
73             return;
74
75         if (priority >= listenersArray.length) {
76             T[][] newListenersArray = allocateTArrayArray(priority + 1);
77             System.arraycopy(listenersArray, 0, newListenersArray, 0, listenersArray.length);
78             for (int i = listenersArray.length; i < priority; i++) {
79                 newListenersArray[i] = emptyTArray();
80             }
81             T[] arr = allocateTArray(1);
82             arr[0] = listener;
83             newListenersArray[priority] = arr;
84             listenersArray = newListenersArray;
85
86         } else { // Add into existing listeners
87
@SuppressWarnings JavaDoc("unchecked")
88             T[][] newListenersArray = (T[][])listenersArray.clone();
89             T[] listeners = listenersArray[priority];
90             T[] newListeners = allocateTArray(listeners.length + 1);
91             System.arraycopy(listeners, 0, newListeners, 1, listeners.length);
92             newListeners[0] = listener;
93             newListenersArray[priority] = newListeners;
94             listenersArray = newListenersArray;
95         }
96     }
97     
98     /**
99      * Remove listener with the given priority index.
100      *
101      * @param listener listener to be removed. If null is passed it is ignored (nothing gets removed).
102      * @param priority &gt;=0 index defining priority
103      * with which the listener was originally added.
104      * <br>
105      * If the listener was not added or it was added with different
106      * priority then no action happens.
107      * @throws IndexOutOfBoundsException when priority &lt; 0
108      */

109     public synchronized void remove(T listener, int priority) {
110         if (listener == null)
111             return;
112
113         if (priority < listenersArray.length) {
114             T[] listeners = listenersArray[priority];
115             // Search from 0 - suppose that later added will sooner be removed
116
int index = 0;
117             while (index < listeners.length && listeners[index] != listener) {
118                 index++;
119             }
120             if (index < listeners.length) {
121                 T[] newListeners;
122                 boolean removeHighestPriorityLevel;
123                 if (listeners.length == 1) {
124                     newListeners = emptyTArray();
125                     removeHighestPriorityLevel = (priority == listenersArray.length - 1);
126                 } else {
127                     newListeners = allocateTArray(listeners.length - 1);
128                     System.arraycopy(listeners, 0, newListeners, 0, index);
129                     System.arraycopy(listeners, index + 1, newListeners, index,
130                             newListeners.length - index);
131                     removeHighestPriorityLevel = false;
132                 }
133                 
134                 
135                 if (removeHighestPriorityLevel) {
136                     T[][] newListenersArray = allocateTArrayArray(listenersArray.length - 1);
137                     System.arraycopy(listenersArray, 0, newListenersArray, 0, newListenersArray.length);
138                     listenersArray = newListenersArray;
139                 } else { // levels count stays the same
140
@SuppressWarnings JavaDoc("unchecked")
141                     T[][] newListenersArray = (T[][])listenersArray.clone();
142                     newListenersArray[priority] = newListeners;
143                     listenersArray = newListenersArray;
144                 }
145             }
146         }
147     }
148
149     /**
150      * Return the actual array of listeners arrays maintained by this listeners list.
151      * <br>
152      * <strong>WARNING!</strong>
153      * Absolutely NO modification should be done on the contents of the returned
154      * data.
155      *
156      * <p>
157      * The higher index means sooner firing. Listeners with the same priority
158      * are ordered so that the one added sooner has higher index than the one
159      * added later. So the following firing mechanism should be used:
160      * </p>
161      * <pre>
162      * private void fireMyEvent(MyEvent evt) {
163      * MyListener[][] listenersArray = priorityListenerList.getListenersArray();
164      * for (int priority = listenersArray.length - 1; priority >= 0; priority--) {
165      * MyListener[] listeners = listenersArray[priority];
166      * for (int i = listeners.length - 1; i >= 0; i--) {
167      * listeners[i].notify(evt);
168      * }
169      * }
170      * }
171      * </pre>
172      */

173     public T[][] getListenersArray() {
174         return listenersArray;
175     }
176
177     // Serialization support.
178
private void writeObject(ObjectOutputStream JavaDoc s) throws IOException JavaDoc {
179         s.defaultWriteObject();
180         
181         // Save serializable event listeners
182
int priority = listenersArray.length - 1; // max priority
183
s.writeInt(priority); // write max priority
184
for (; priority >= 0; priority--) {
185             T[] listeners = listenersArray[priority];
186             // Write in opposite order of adding
187
for (int i = 0; i < listeners.length; i++) {
188                 T listener = listeners[i];
189                 // Save only the serializable listeners
190
if (listener instanceof Serializable JavaDoc) {
191                     s.writeObject(listener);
192                 }
193             }
194             s.writeObject(null);
195         }
196     }
197     
198     private void readObject(ObjectInputStream JavaDoc s)
199     throws IOException JavaDoc, ClassNotFoundException JavaDoc {
200         s.defaultReadObject();
201         int priority = s.readInt();
202         listenersArray = (priority != -1)
203             ? allocateTArrayArray(priority + 1)
204             : emptyTArrayArray();
205
206         for (; priority >= 0; priority--) {
207             List JavaDoc<T> lList = new ArrayList JavaDoc<T>();
208             Object JavaDoc listenerOrNull;
209             while (null != (listenerOrNull = s.readObject())) {
210                 @SuppressWarnings JavaDoc("unchecked")
211                 T l = (T)listenerOrNull;
212                 lList.add(l);
213             }
214             @SuppressWarnings JavaDoc("unchecked")
215             T[] lArr = (T[])lList.toArray(new EventListener JavaDoc[lList.size()]);
216             listenersArray[priority] = lArr;
217         }
218     }
219     
220     @SuppressWarnings JavaDoc("unchecked")
221     private T[] emptyTArray() {
222         return (T[])EMPTY_LISTENER_ARRAY;
223     }
224
225     @SuppressWarnings JavaDoc("unchecked")
226     private T[][] emptyTArrayArray() {
227         return (T[][])EMPTY_LISTENER_ARRAY_ARRAY;
228     }
229
230     @SuppressWarnings JavaDoc("unchecked")
231     private T[] allocateTArray(int length) {
232         return (T[])new EventListener JavaDoc[length];
233     }
234
235     @SuppressWarnings JavaDoc("unchecked")
236     private T[][] allocateTArrayArray(int length) {
237         return (T[][])new EventListener JavaDoc[length][];
238     }
239
240 }
241
Popular Tags