KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > core > internal > databinding > internal > beans > ListenerSupport


1 /*******************************************************************************
2  * Copyright (c) 2005, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11 package org.eclipse.core.internal.databinding.internal.beans;
12
13 import java.beans.PropertyChangeEvent JavaDoc;
14 import java.beans.PropertyChangeListener JavaDoc;
15 import java.lang.reflect.InvocationTargetException JavaDoc;
16 import java.lang.reflect.Method JavaDoc;
17 import java.util.HashSet JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.Set JavaDoc;
20
21 import org.eclipse.core.databinding.beans.BeansObservables;
22 import org.eclipse.core.databinding.util.Policy;
23 import org.eclipse.core.runtime.Assert;
24 import org.eclipse.core.runtime.IStatus;
25 import org.eclipse.core.runtime.Status;
26
27 /**
28  * This is a helper that will hook up and listen for <code>PropertyChangeEvent</code> events
29  * for a set of target JavaBeans
30  *
31  * @since 1.0
32  */

33 public class ListenerSupport {
34
35     private Set JavaDoc elementsListenedTo = new HashSet JavaDoc();
36     
37     private PropertyChangeListener JavaDoc listener;
38
39     private String JavaDoc propertyName;
40
41     /**
42      * Constructs a new instance.
43      *
44      * @param listener is the callback that will be called
45      * when a <code>PropertyChangeEvent</code> is fired on any
46      * of the target objects. Will only receive change events
47      * when the provided <code>propertyName</code> changes.
48      * @param propertyName
49      */

50     public ListenerSupport(final PropertyChangeListener JavaDoc listener,
51             final String JavaDoc propertyName) {
52         Assert.isNotNull(listener);
53         Assert.isNotNull(propertyName);
54
55         this.propertyName = propertyName;
56         this.listener = new PropertyChangeListener JavaDoc() {
57             public void propertyChange(PropertyChangeEvent JavaDoc evt) {
58                 if (propertyName.equals(evt.getPropertyName())) {
59                     listener.propertyChange(evt);
60                 }
61             }
62         };
63     }
64
65     /**
66      * Start listen to target (if it supports the JavaBean property change listener pattern)
67      *
68      * @param target
69      */

70     public void hookListener(Object JavaDoc target) {
71         if (processListener(
72                 "addPropertyChangeListener", "Could not attach listener to ", target)) { //$NON-NLS-1$ //$NON-NLS-2$
73
elementsListenedTo.add(new IdentityWrapper(target));
74         }
75     }
76         
77     /**
78      * Add listeners for new targets (those this instance of<code>ListenerSupport</code> does not
79      * already listen to),
80      * Stop to listen to those object that this instance listen to and is one of the object in targets
81      *
82      * @param targets
83      */

84     public void setHookTargets(Object JavaDoc[] targets) {
85         Set JavaDoc elementsToUnhook = new HashSet JavaDoc(elementsListenedTo);
86         if (targets!=null) {
87             for (int i = 0; i < targets.length; i++) {
88                 Object JavaDoc newValue = targets[i];
89                 IdentityWrapper identityWrapper = new IdentityWrapper(newValue);
90                 if(!elementsToUnhook.remove(identityWrapper))
91                     hookListener(newValue);
92             }
93         }
94             
95         for (Iterator JavaDoc it = elementsToUnhook.iterator(); it.hasNext();) {
96             Object JavaDoc o = it.next();
97             if (o.getClass()!=IdentityWrapper.class)
98                 o = new IdentityWrapper(o);
99             elementsListenedTo.remove(o);
100             unhookListener(o);
101         }
102     }
103     
104     /**
105      * Stop listen to target
106      *
107      * @param target
108      */

109     public void unhookListener(Object JavaDoc target) {
110         if (target.getClass() == IdentityWrapper.class)
111             target = ((IdentityWrapper) target).unwrap();
112
113         if (processListener(
114                 "removePropertyChangeListener", "Cound not remove listener from ", target)) { //$NON-NLS-1$//$NON-NLS-2$
115
elementsListenedTo.remove(new IdentityWrapper(target));
116         }
117     }
118     
119     
120     /**
121      *
122      */

123     public void dispose() {
124         if (elementsListenedTo!=null) {
125             Object JavaDoc[] targets = elementsListenedTo.toArray();
126             for (int i = 0; i < targets.length; i++) {
127                 unhookListener(targets[i]);
128             }
129             elementsListenedTo=null;
130             listener=null;
131         }
132     }
133     
134     /**
135      * @return elements that were registred to
136      */

137     public Object JavaDoc[] getHookedTargets() {
138         Object JavaDoc[] targets = null;
139         if (elementsListenedTo!=null && elementsListenedTo.size()>0) {
140             Object JavaDoc[] identityList = elementsListenedTo.toArray();
141             targets = new Object JavaDoc[identityList.length];
142             for (int i = 0; i < identityList.length; i++)
143                 targets[i]=((IdentityWrapper)identityList[i]).unwrap();
144         }
145         return targets;
146     }
147
148     /**
149      * Invokes the method for the provided <code>methodName</code> attempting
150      * to first use the method with the property name and then the unnamed
151      * version.
152      *
153      * @param methodName
154      * either addPropertyChangeListener or
155      * removePropertyChangeListener
156      * @param message
157      * string that will be prefixed to the target in an error message
158      * @param target
159      * object to invoke the method on
160      * @return <code>true</code> if the method was invoked successfully
161      */

162     private boolean processListener(String JavaDoc methodName, String JavaDoc message,
163             Object JavaDoc target) {
164         Method JavaDoc method = null;
165         Object JavaDoc[] parameters = null;
166
167         try {
168             try {
169                 method = target.getClass().getMethod(
170                         methodName,
171                         new Class JavaDoc[] { String JavaDoc.class,
172                                 PropertyChangeListener JavaDoc.class });
173
174                 parameters = new Object JavaDoc[] { propertyName, listener };
175             } catch (NoSuchMethodException JavaDoc e) {
176                 method = target.getClass().getMethod(methodName,
177                         new Class JavaDoc[] { PropertyChangeListener JavaDoc.class });
178
179                 parameters = new Object JavaDoc[] { listener };
180             }
181         } catch (SecurityException JavaDoc e) {
182             // ignore
183
} catch (NoSuchMethodException JavaDoc e) {
184             log(IStatus.WARNING, message + target, e);
185         }
186
187         if (method != null) {
188             if (!method.isAccessible()) {
189                 method.setAccessible(true);
190             }
191             try {
192                 method.invoke(target, parameters);
193                 return true;
194             } catch (IllegalArgumentException JavaDoc e) {
195                 log(IStatus.WARNING, message + target, e);
196             } catch (IllegalAccessException JavaDoc e) {
197                 log(IStatus.WARNING, message + target, e);
198             } catch (InvocationTargetException JavaDoc e) {
199                 log(IStatus.WARNING, message + target, e);
200             }
201         }
202         return false;
203     }
204
205     /**
206      * Logs a message to the Data Binding logger.
207      */

208     private void log(int severity, String JavaDoc message, Throwable JavaDoc throwable) {
209         if (BeansObservables.DEBUG) {
210             Policy.getLog().log(
211                     new Status(severity, Policy.JFACE_DATABINDING, IStatus.OK,
212                             message, throwable));
213         }
214     }
215 }
216
Popular Tags