Source Code Cross Referenced for PropertyChangeSupport.java in  » 6.0-JDK-Core » beans » java » beans » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » beans » java.beans 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1996-2006 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package java.beans;
027
028        import java.io.Serializable;
029        import java.io.ObjectOutputStream;
030        import java.io.ObjectInputStream;
031        import java.io.IOException;
032        import java.util.Arrays;
033        import java.util.ArrayList;
034        import java.util.Iterator;
035        import java.util.List;
036
037        import sun.awt.EventListenerAggregate;
038
039        /**
040         * This is a utility class that can be used by beans that support bound
041         * properties.  You can use an instance of this class as a member field
042         * of your bean and delegate various work to it.
043         *
044         * This class is serializable.  When it is serialized it will save
045         * (and restore) any listeners that are themselves serializable.  Any
046         * non-serializable listeners will be skipped during serialization.
047         *
048         */
049        public class PropertyChangeSupport implements  java.io.Serializable {
050
051            // Manages the listener list.
052            private transient EventListenerAggregate listeners;
053
054            /**
055             * Constructs a <code>PropertyChangeSupport</code> object.
056             *
057             * @param sourceBean  The bean to be given as the source for any events.
058             */
059
060            public PropertyChangeSupport(Object sourceBean) {
061                if (sourceBean == null) {
062                    throw new NullPointerException();
063                }
064                source = sourceBean;
065            }
066
067            /**
068             * Add a PropertyChangeListener to the listener list.
069             * The listener is registered for all properties.
070             * The same listener object may be added more than once, and will be called
071             * as many times as it is added.
072             * If <code>listener</code> is null, no exception is thrown and no action
073             * is taken.
074             *
075             * @param listener  The PropertyChangeListener to be added
076             */
077            public synchronized void addPropertyChangeListener(
078                    PropertyChangeListener listener) {
079                if (listener == null) {
080                    return;
081                }
082
083                if (listener instanceof  PropertyChangeListenerProxy) {
084                    PropertyChangeListenerProxy proxy = (PropertyChangeListenerProxy) listener;
085                    // Call two argument add method.
086                    addPropertyChangeListener(proxy.getPropertyName(),
087                            (PropertyChangeListener) proxy.getListener());
088                } else {
089                    if (listeners == null) {
090                        listeners = new EventListenerAggregate(
091                                PropertyChangeListener.class);
092                    }
093                    listeners.add(listener);
094                }
095            }
096
097            /**
098             * Remove a PropertyChangeListener from the listener list.
099             * This removes a PropertyChangeListener that was registered
100             * for all properties.
101             * If <code>listener</code> was added more than once to the same event
102             * source, it will be notified one less time after being removed.
103             * If <code>listener</code> is null, or was never added, no exception is
104             * thrown and no action is taken.
105             *
106             * @param listener  The PropertyChangeListener to be removed
107             */
108            public synchronized void removePropertyChangeListener(
109                    PropertyChangeListener listener) {
110                if (listener == null) {
111                    return;
112                }
113
114                if (listener instanceof  PropertyChangeListenerProxy) {
115                    PropertyChangeListenerProxy proxy = (PropertyChangeListenerProxy) listener;
116                    // Call two argument remove method.
117                    removePropertyChangeListener(proxy.getPropertyName(),
118                            (PropertyChangeListener) proxy.getListener());
119                } else {
120                    if (listeners == null) {
121                        return;
122                    }
123                    listeners.remove(listener);
124                }
125            }
126
127            /**
128             * Returns an array of all the listeners that were added to the
129             * PropertyChangeSupport object with addPropertyChangeListener().
130             * <p>
131             * If some listeners have been added with a named property, then
132             * the returned array will be a mixture of PropertyChangeListeners
133             * and <code>PropertyChangeListenerProxy</code>s. If the calling
134             * method is interested in distinguishing the listeners then it must
135             * test each element to see if it's a
136             * <code>PropertyChangeListenerProxy</code>, perform the cast, and examine
137             * the parameter.
138             * 
139             * <pre>
140             * PropertyChangeListener[] listeners = bean.getPropertyChangeListeners();
141             * for (int i = 0; i < listeners.length; i++) {
142             *	 if (listeners[i] instanceof PropertyChangeListenerProxy) {
143             *     PropertyChangeListenerProxy proxy = 
144             *                    (PropertyChangeListenerProxy)listeners[i];
145             *     if (proxy.getPropertyName().equals("foo")) {
146             *       // proxy is a PropertyChangeListener which was associated
147             *       // with the property named "foo"
148             *     }
149             *   }
150             * }
151             *</pre>
152             *
153             * @see PropertyChangeListenerProxy
154             * @return all of the <code>PropertyChangeListeners</code> added or an 
155             *         empty array if no listeners have been added
156             * @since 1.4
157             */
158            public synchronized PropertyChangeListener[] getPropertyChangeListeners() {
159                List returnList = new ArrayList();
160
161                // Add all the PropertyChangeListeners 
162                if (listeners != null) {
163                    returnList.addAll(Arrays.asList(listeners
164                            .getListenersInternal()));
165                }
166
167                // Add all the PropertyChangeListenerProxys
168                if (children != null) {
169                    Iterator iterator = children.keySet().iterator();
170                    while (iterator.hasNext()) {
171                        String key = (String) iterator.next();
172                        PropertyChangeSupport child = (PropertyChangeSupport) children
173                                .get(key);
174                        PropertyChangeListener[] childListeners = child
175                                .getPropertyChangeListeners();
176                        for (int index = childListeners.length - 1; index >= 0; index--) {
177                            returnList.add(new PropertyChangeListenerProxy(key,
178                                    childListeners[index]));
179                        }
180                    }
181                }
182                return (PropertyChangeListener[]) (returnList
183                        .toArray(new PropertyChangeListener[0]));
184            }
185
186            /**
187             * Add a PropertyChangeListener for a specific property.  The listener
188             * will be invoked only when a call on firePropertyChange names that
189             * specific property.
190             * The same listener object may be added more than once.  For each
191             * property,  the listener will be invoked the number of times it was added
192             * for that property.
193             * If <code>propertyName</code> or <code>listener</code> is null, no
194             * exception is thrown and no action is taken.
195             *
196             * @param propertyName  The name of the property to listen on.
197             * @param listener  The PropertyChangeListener to be added
198             */
199
200            public synchronized void addPropertyChangeListener(
201                    String propertyName, PropertyChangeListener listener) {
202                if (listener == null || propertyName == null) {
203                    return;
204                }
205                if (children == null) {
206                    children = new java.util.Hashtable();
207                }
208                PropertyChangeSupport child = (PropertyChangeSupport) children
209                        .get(propertyName);
210                if (child == null) {
211                    child = new PropertyChangeSupport(source);
212                    children.put(propertyName, child);
213                }
214                child.addPropertyChangeListener(listener);
215            }
216
217            /**
218             * Remove a PropertyChangeListener for a specific property.
219             * If <code>listener</code> was added more than once to the same event
220             * source for the specified property, it will be notified one less time
221             * after being removed.
222             * If <code>propertyName</code> is null,  no exception is thrown and no
223             * action is taken.
224             * If <code>listener</code> is null, or was never added for the specified
225             * property, no exception is thrown and no action is taken.
226             *
227             * @param propertyName  The name of the property that was listened on.
228             * @param listener  The PropertyChangeListener to be removed
229             */
230
231            public synchronized void removePropertyChangeListener(
232                    String propertyName, PropertyChangeListener listener) {
233                if (listener == null || propertyName == null) {
234                    return;
235                }
236                if (children == null) {
237                    return;
238                }
239                PropertyChangeSupport child = (PropertyChangeSupport) children
240                        .get(propertyName);
241                if (child == null) {
242                    return;
243                }
244                child.removePropertyChangeListener(listener);
245            }
246
247            /**
248             * Returns an array of all the listeners which have been associated 
249             * with the named property.
250             *
251             * @param propertyName  The name of the property being listened to
252             * @return all of the <code>PropertyChangeListeners</code> associated with
253             *         the named property.  If no such listeners have been added,
254             *         or if <code>propertyName</code> is null, an empty array is
255             *         returned.
256             * @since 1.4
257             */
258            public synchronized PropertyChangeListener[] getPropertyChangeListeners(
259                    String propertyName) {
260                ArrayList returnList = new ArrayList();
261
262                if (children != null && propertyName != null) {
263                    PropertyChangeSupport support = (PropertyChangeSupport) children
264                            .get(propertyName);
265                    if (support != null) {
266                        returnList.addAll(Arrays.asList(support
267                                .getPropertyChangeListeners()));
268                    }
269                }
270                return (PropertyChangeListener[]) (returnList
271                        .toArray(new PropertyChangeListener[0]));
272            }
273
274            /**
275             * Report a bound property update to any registered listeners.
276             * No event is fired if old and new are equal and non-null.
277             *
278             * <p>
279             * This is merely a convenience wrapper around the more general
280             * firePropertyChange method that takes {@code
281             * PropertyChangeEvent} value.
282             *
283             * @param propertyName  The programmatic name of the property
284             *		that was changed.
285             * @param oldValue  The old value of the property.
286             * @param newValue  The new value of the property.
287             */
288            public void firePropertyChange(String propertyName,
289                    Object oldValue, Object newValue) {
290                if (oldValue != null && newValue != null
291                        && oldValue.equals(newValue)) {
292                    return;
293                }
294                firePropertyChange(new PropertyChangeEvent(source,
295                        propertyName, oldValue, newValue));
296            }
297
298            /**
299             * Report an int bound property update to any registered listeners.
300             * No event is fired if old and new are equal.
301             * <p>
302             * This is merely a convenience wrapper around the more general
303             * firePropertyChange method that takes Object values.
304             *
305             * @param propertyName  The programmatic name of the property
306             *		that was changed.
307             * @param oldValue  The old value of the property.
308             * @param newValue  The new value of the property.
309             */
310            public void firePropertyChange(String propertyName, int oldValue,
311                    int newValue) {
312                if (oldValue == newValue) {
313                    return;
314                }
315                firePropertyChange(propertyName, new Integer(oldValue),
316                        new Integer(newValue));
317            }
318
319            /**
320             * Report a boolean bound property update to any registered listeners.
321             * No event is fired if old and new are equal.
322             * <p>
323             * This is merely a convenience wrapper around the more general
324             * firePropertyChange method that takes Object values.
325             *
326             * @param propertyName  The programmatic name of the property
327             *		that was changed.
328             * @param oldValue  The old value of the property.
329             * @param newValue  The new value of the property.
330             */
331            public void firePropertyChange(String propertyName,
332                    boolean oldValue, boolean newValue) {
333                if (oldValue == newValue) {
334                    return;
335                }
336                firePropertyChange(propertyName, Boolean.valueOf(oldValue),
337                        Boolean.valueOf(newValue));
338            }
339
340            /**
341             * Fire an existing PropertyChangeEvent to any registered listeners.
342             * No event is fired if the given event's old and new values are
343             * equal and non-null.
344             * @param evt  The PropertyChangeEvent object.
345             */
346            public void firePropertyChange(PropertyChangeEvent evt) {
347                Object oldValue = evt.getOldValue();
348                Object newValue = evt.getNewValue();
349                String propertyName = evt.getPropertyName();
350                if (oldValue != null && newValue != null
351                        && oldValue.equals(newValue)) {
352                    return;
353                }
354
355                if (listeners != null) {
356                    Object[] list = listeners.getListenersInternal();
357                    for (int i = 0; i < list.length; i++) {
358                        PropertyChangeListener target = (PropertyChangeListener) list[i];
359                        target.propertyChange(evt);
360                    }
361                }
362
363                if (children != null && propertyName != null) {
364                    PropertyChangeSupport child = null;
365                    child = (PropertyChangeSupport) children.get(propertyName);
366                    if (child != null) {
367                        child.firePropertyChange(evt);
368                    }
369                }
370            }
371
372            /**
373             * Report a bound indexed property update to any registered
374             * listeners. 
375             * <p>
376             * No event is fired if old and new values are equal
377             * and non-null.
378             *
379             * <p>
380             * This is merely a convenience wrapper around the more general
381             * firePropertyChange method that takes {@code PropertyChangeEvent} value.
382             *
383             * @param propertyName The programmatic name of the property that
384             *                     was changed.
385             * @param index        index of the property element that was changed.
386             * @param oldValue     The old value of the property.
387             * @param newValue     The new value of the property.
388             * @since 1.5
389             */
390            public void fireIndexedPropertyChange(String propertyName,
391                    int index, Object oldValue, Object newValue) {
392                firePropertyChange(new IndexedPropertyChangeEvent(source,
393                        propertyName, oldValue, newValue, index));
394            }
395
396            /**
397             * Report an <code>int</code> bound indexed property update to any registered 
398             * listeners. 
399             * <p>
400             * No event is fired if old and new values are equal.
401             * <p>
402             * This is merely a convenience wrapper around the more general
403             * fireIndexedPropertyChange method which takes Object values.
404             *
405             * @param propertyName The programmatic name of the property that
406             *                     was changed.
407             * @param index        index of the property element that was changed.
408             * @param oldValue     The old value of the property.
409             * @param newValue     The new value of the property.
410             * @since 1.5
411             */
412            public void fireIndexedPropertyChange(String propertyName,
413                    int index, int oldValue, int newValue) {
414                if (oldValue == newValue) {
415                    return;
416                }
417                fireIndexedPropertyChange(propertyName, index, new Integer(
418                        oldValue), new Integer(newValue));
419            }
420
421            /**
422             * Report a <code>boolean</code> bound indexed property update to any 
423             * registered listeners. 
424             * <p>
425             * No event is fired if old and new values are equal.
426             * <p>
427             * This is merely a convenience wrapper around the more general
428             * fireIndexedPropertyChange method which takes Object values.
429             *
430             * @param propertyName The programmatic name of the property that
431             *                     was changed.
432             * @param index        index of the property element that was changed.
433             * @param oldValue     The old value of the property.
434             * @param newValue     The new value of the property.
435             * @since 1.5
436             */
437            public void fireIndexedPropertyChange(String propertyName,
438                    int index, boolean oldValue, boolean newValue) {
439                if (oldValue == newValue) {
440                    return;
441                }
442                fireIndexedPropertyChange(propertyName, index, Boolean
443                        .valueOf(oldValue), Boolean.valueOf(newValue));
444            }
445
446            /**
447             * Check if there are any listeners for a specific property, including
448             * those registered on all properties.  If <code>propertyName</code>
449             * is null, only check for listeners registered on all properties.
450             *
451             * @param propertyName  the property name.
452             * @return true if there are one or more listeners for the given property
453             */
454            public synchronized boolean hasListeners(String propertyName) {
455                if (listeners != null && !listeners.isEmpty()) {
456                    // there is a generic listener
457                    return true;
458                }
459                if (children != null && propertyName != null) {
460                    PropertyChangeSupport child = (PropertyChangeSupport) children
461                            .get(propertyName);
462                    if (child != null && child.listeners != null) {
463                        return !child.listeners.isEmpty();
464                    }
465                }
466                return false;
467            }
468
469            /**
470             * @serialData Null terminated list of <code>PropertyChangeListeners</code>.
471             * <p>
472             * At serialization time we skip non-serializable listeners and
473             * only serialize the serializable listeners.
474             *
475             */
476            private void writeObject(ObjectOutputStream s) throws IOException {
477                s.defaultWriteObject();
478
479                if (listeners != null) {
480                    Object[] list = listeners.getListenersCopy();
481
482                    for (int i = 0; i < list.length; i++) {
483                        PropertyChangeListener l = (PropertyChangeListener) list[i];
484                        if (l instanceof  Serializable) {
485                            s.writeObject(l);
486                        }
487                    }
488                }
489                s.writeObject(null);
490            }
491
492            private void readObject(ObjectInputStream s)
493                    throws ClassNotFoundException, IOException {
494                s.defaultReadObject();
495
496                Object listenerOrNull;
497                while (null != (listenerOrNull = s.readObject())) {
498                    addPropertyChangeListener((PropertyChangeListener) listenerOrNull);
499                }
500            }
501
502            /** 
503             * Hashtable for managing listeners for specific properties.
504             * Maps property names to PropertyChangeSupport objects.
505             * @serial 
506             * @since 1.2
507             */
508            private java.util.Hashtable children;
509
510            /** 
511             * The object to be provided as the "source" for any generated events.
512             * @serial
513             */
514            private Object source;
515
516            /**
517             * Internal version number
518             * @serial
519             * @since
520             */
521            private int propertyChangeSupportSerializedDataVersion = 2;
522
523            /**
524             * Serialization version ID, so we're compatible with JDK 1.1
525             */
526            static final long serialVersionUID = 6401253773779951803L;
527        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.