KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > objectweb > jac > aspects > queue > MessageQueue


1 /*
2   Copyright (C) 2003 Laurent Martelli <laurent@aopsys.com>
3   
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU Lesser General Public License as
6   published by the Free Software Foundation; either version 2 of the
7   License, or (at your option) any later version.
8
9   This program is distributed in the hope that it will be useful, but
10   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 program; if not, write to the Free Software
16   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17   USA */

18
19 package org.objectweb.jac.aspects.queue;
20
21
22
23 import org.objectweb.jac.core.rtti.FieldItem;
24 import org.objectweb.jac.core.rtti.MethodItem;
25 import java.util.Collections JavaDoc;
26 import java.util.HashMap JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.LinkedList JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Map JavaDoc;
31 import java.util.Set JavaDoc;
32 import org.objectweb.jac.util.Log;
33
34
35 /**
36  * Handles an asynchronous message queue.
37  */

38 public class MessageQueue {
39
40    NotifyThread thread;
41    public MessageQueue() {
42       thread = new NotifyThread();
43       thread.start();
44    }
45
46    // FieldItem -> Set of MethodItem
47
HashMap JavaDoc fieldClients = new HashMap JavaDoc();
48
49    /**
50     * Gets the map of field change client callbacks.
51     * @return a Map whose keys are of type FieldItem, and whose values
52     * are sets of MethodItem
53     */

54    public Map JavaDoc getFieldClients() {
55       return fieldClients;
56    }
57
58    List JavaDoc queue = Collections.synchronizedList(new LinkedList JavaDoc());
59
60    /**
61     * Send a message to the queue saying that the field of an object
62     * has changed, so that it will be sent to all registered clients.
63     * @param substance the object whose field has changed
64     * @param field the field that changed
65     */

66    public void fieldChanged(Object JavaDoc substance, FieldItem field,
67                             Object JavaDoc previousValue, Object JavaDoc currentValue) {
68       Log.trace("mqueue","fieldChanged("+substance+","+field+","+
69                 previousValue+" -> "+currentValue);
70       queue.add(new FieldChangeEvent(substance,field,previousValue,currentValue));
71       thread.notifyClients();
72    }
73
74    /**
75     * Register for the changes of a field.
76     * @param field the field to register for
77     * @param callback a static method to be called when the field changes.
78     * @see #unregisterFieldChange(FieldItem,MethodItem)
79     */

80    public void registerFieldChange(FieldItem field, MethodItem callback) {
81       Set JavaDoc clients = (Set JavaDoc)fieldClients.get(field);
82       if (clients==null) {
83          clients = new HashSet JavaDoc();
84          fieldClients.put(field,clients);
85       }
86       clients.add(callback);
87    }
88
89    /**
90     * Notify registered clients of a field change.
91     * @param event the FieldChangeEvent to dispatch
92     */

93    public void notifyFieldChange(FieldChangeEvent event) {
94       Set JavaDoc clients = (Set JavaDoc)fieldClients.get(event.getField());
95       if (clients!=null) {
96          MethodItem[] array = (MethodItem[])clients.toArray(new MethodItem[] {});
97          Object JavaDoc[] params = new Object JavaDoc[] {event};
98          for(int i=0; i<array.length; i++) {
99             try {
100                Log.warning("mqueue","notifying "+event+" to "+array[i]);
101                array[i].invokeStatic(params);
102             } catch (Exception JavaDoc e) {
103                Log.warning("mqueue","Failed to invoke "+array[i]+": "+e);
104             }
105          }
106       }
107    }
108
109    /**
110     * Unregister for the changes of a field.
111     * @param field the field to unregister from
112     * @param callback a static method to to call anymore when the
113     * field changes.
114     * @see #registerFieldChange(FieldItem,MethodItem) */

115    public void unregisterFieldChange(FieldItem field, MethodItem callback) {
116       Set JavaDoc clients = (Set JavaDoc)fieldClients.get(field);
117       if (clients!=null) {
118          clients.remove(callback);
119       }
120    }
121
122    class NotifyThread extends Thread JavaDoc {
123       public void run() {
124          while (true) {
125             try {
126                synchronized(this) {
127                   this.wait();
128                }
129             } catch (InterruptedException JavaDoc e) {
130             }
131             Log.trace("mqueue","Queue = "+queue);
132             if (!queue.isEmpty()) {
133                Object JavaDoc events[] = queue.toArray();
134                for (int i=0; i<events.length; i++) {
135                   if (events[i] instanceof FieldChangeEvent) {
136                      FieldChangeEvent event = (FieldChangeEvent)events[i];
137                      notifyFieldChange(event);
138                      queue.remove(event);
139                   }
140                }
141             }
142          }
143       }
144
145       /**
146        * Call this method when a new event was added to the queue.
147        */

148       public synchronized void notifyClients() {
149          this.notify();
150       }
151    }
152 }
153
Popular Tags